likes
comments
collection
share

如何优雅的使用react router v6, 并实现全局守卫

作者站长头像
站长
· 阅读数 45

前言

哈喽大家好,我是Charlie,最近想把react补起来,总觉得只有Vue出门没安全感,更不好意思说自己是个前端攻城狮,所以抽空开始把react搞起来,今天给大家分享最近的心得和其中一些操作,对啦,最近发现react的官网也更新了,旧的官网,新版中文官网,同时建议大家有空多看看原版英文官网,废话不多说,开干!!!

1.项目初始化

首先用一句话简单总结下react是什么? React 是一个用于构建用户界面的 JavaScript 库 对于项目初始化这话,react也有自己的脚手架Create React App,react官网也是建议我们初学者使用CRA去初始化一个react项目,奈何这个这个脚手架太鸡肋,好多东西都需要开发者手动去配置,另外是基于webpack的,所以项目大的时候配置起来是及其麻烦,那怎么办呢? 还好有尤大的vite,vite也支持快速生成react项目,并内置一些基础配置,使用起来是真香 套用几句vite官网的介绍:

pnpm create vite

我们取名为react-ts,然后选择react技术栈,以及TypeScript语言

如何优雅的使用react router v6, 并实现全局守卫 ok,项目初始化完毕后,我们运行如下,标识已经初始化成功!

如何优雅的使用react router v6, 并实现全局守卫

2.react-router v6简单介绍

react router 发布了三个不同的包:

  • react-router:路由核心库,提供许多组件、钩子;
  • react-router-dom: 包括了 react-router 所有内容,同时添加了用于 DOM 的组件,如 <BrowserRouter>
  • react-router-native: 包括了 react-router 所有内容,同时添加了用于 ReactNative 的 API,如<NativeRouter>

与react-router 5.X区别:

  • 内置组件的变化:移除 <Switch/>,新增 <Routes/>……
  • 语法变化:component={About} 变成 element={<About/>}……
  • 新增 hook:useParamsuseNavigateuseMatch……
  • 官方明确表示推荐使用函数式组件

3.使用react route v6创建路由表

首先我们先安装react router v6以及依赖

pnpm install react-router router-router-dom

安装完路由后,我们也想使用vue那样,单独创建一个路由表,用来管理路由。

#依次执行下面代码
cd src
mkdir routes
touch index.tsx

我们首先创建两个页面,一个home页面,一个about页面,然后再routes/index.tsx中引入,那是否可以像vue那样实现路由懒加载呢,答案是当然可以,react也为我们光大开发者提供了一个懒加载的api,就是React.lazy(),通过这个方法,我们就可以实现路由懒加载

const Home = React.lazy(() => import('../pages/Home'))
const About = React.lazy(() => import('../pages/About'))

interface Route {
  path: string,
  name: string,
  element: ReactNode
}
export const routes: Route[] = [
  {
    path: '/home',
    name: 'home',
    element: <Home />
  },
  {
    path: '/about',
    name: 'about',
    element: <About />
  },
]

ok 路由表建立后我们如何在页面中优雅的展示呢? 这里不得不提useRoutes这个hooks, 他能够将我们创建的路由表一一映射成为路由对象 我们也想vue开发中一样,在App.tsx中引入刚才我们创建好的路由表,

function App() {
  const elements = useRoutes(generateRouter(routes))
  return (
    <div>
      {elements}
    </div>
  )
}

这样一个简单的路由表就创建好了,但是开发中,我们肯定不会是这么简单,比如,切换路由时我们可以增加loading转场等,react也为我们提供了React.Suspense组件,通过callback props传入一个loading,来实现转场效果,我们用该组件将上面的elements封装下

<React.Suspense fallback={<Loading/>}>
   {elements}
</React.Suspense>

封装完后,在切换路由时,会发现有一个loading转场的一个效果。

4.增加全局守卫

如果是一个大型项目,那简单的路由表肯定是不能满足我们的需求的,比如常见的权限校验,前置逻辑等等就无法处理。那react-router没有像vue一样的类似全局守卫的函数吗? 那还真没有,不得不说react是真的优秀,什么都需要自己手动去搞定,搞就搞,谁怕谁,哈哈哈哈 无非我们就是实现一个高阶组件包裹下,然后再高阶组件里面我们去做下路由拦截处理和前置逻辑处理 我们首先对刚才的路由表进行扩展,我们先增加一个权限校验和子组件吧

interface Route {
  path: string,
  name: string,
  element: ReactNode,
  children?: Route[],
  auth?: boolean
}
export const routes: Route[] = [
  {
    path: '/home',
    name: 'home',
    element: <Home />
    auth: true
  },
  {
    path: '/about',
    name: 'about',
    element: <About />
  },
]

紧接着需要对上面的路由表实现一个类似中间件的映射,首先实现一个RouterBeforeEach高阶组件,参数为外部传入的routes,在该组件内部,将上面我们写的routes和传入的做一个对比和判断,如果有auth并且为true,则需要做权限校验,如果没有,则不需要。

export const RouterBeforeEach = ({children}: any) => {
  const location = useLocation();
  const navigator =useNavigate()
  useEffect(() => {
    let router = getCurrentRouterMap(routes, location.pathname)
    if(!isLogin && router.auth) {
      navigator('/login')
    }
  }, [location.pathname]);
  return children
}

另外上面的两个hooks:

  • useLocation: 这个钩子返回当前路由对象。如果您想在当前路由更改时执行一些副作用,我们就可以使用这个hooks。
  • useNavigate: useNavigate钩子返回一个函数,这个hooks能够让我可以编程式的导航。

上面的getCurrentRouterMap就是在路由表中获取到当前的路由对应的路由

const getCurrentRouterMap = (routers: Router[], path: string): Route => {
  for(let router of routers) {
    if(router.path == path) return router;
    if(router.child) {
      const childRouter = getCurrentRouterMap(router.child, path)
      if(childRouter) return childRouter;
    }
  }
  return routes[routes.length -1]
}

然后,我们在去App.tsx中用RouterBeforeEach包裹下elements

 <React.Suspense fallback={<Loading/>}>
    <RouterBeforeEach>
      {elements}
    </RouterBeforeEach>
  </React.Suspense>
</div>

ok,到这里用react-router 6实现一个路由表,并实现一个全局守卫已经完成。

5.总结

总的来说,react对初学者确实比vue要要求高些,很多东西需要自己手动去封装和处理,不像vue,在框架层面已经帮我们做了太多的处理,对开发者还是非常友好的;但是不能说react就不友好,只能说各有各的好处,相信坚持下去他会给我们能力上带来很大的提升。 好了,喜欢的小伙伴赶紧手动实践起来吧。

转载自:https://juejin.cn/post/7222787944297791543
评论
请登录