• react+ts之router管理


    一、路由中心化思想不动摇

    实际开发中,我们仍然希望看到是一个路由的JSON体,能很清楚的了解整个路由结构,在react中有点不一样的是需要循环出路由组件,并在全局中使用。所以我们可以自己建立一个JSON体用来循环数据,达到我们想要的效果,有时涉及到权限管理时,常见的像后台应用,我们也可以根据请求结果的JSON进行循环,区别无疑是本地和非本地而已。

    如果是接口请求来的,可以结合store保留接口请求过来的menu的菜单list,顺便做个持久化存储

    剩下的那我们就要保证路由与本地目录是完全匹配的,通过一次性的递归,动态匹配router与component并生成如下图的格式,或者以下图格式为global路由在此基础上进行数组合并:
    在这里插入图片描述

    二、封装路由组件需要全局使用一次

    这里通过useRouteshook注册了路由组件,利用RegisterRouter递归处理了router的结构体,使用useMemo避免了页面更新带来的重复执行的陷阱

    // router/index.tsx
    import React, { Suspense,useMemo } from 'react';
    import { useRoutes, RouteObject } from 'react-router-dom'
    import { Spin } from 'antd'
    import Route from './routes'
    import { SyncRoute } from './route.d'
    
    const routes: SyncRoute.Routes[] = [
     ...Route
     //  加上你store 保存的路由集合的合并分类,仅加载执行一次 注入到Route中
    ]
    const RegisterRouter = (routes: SyncRoute.Routes[]): RouteObject[] => {
      const SyncRouter = (routes: SyncRoute.Routes[]): RouteObject[] => {
        let mRouteTable: RouteObject[] = []
        
        routes.forEach(route => {
          mRouteTable.push({
            path: route.path,
            element: (
              <Suspense fallback={ <Spin tip="Loading..."></Spin> }>
                <route.component role={route.meta?.buttonList}/>
              </Suspense>
            ),
            children: route.children &&  SyncRouter(route.children)
          })
        })
        return mRouteTable
      }
      return SyncRouter(routes)
    }
    
    export default () => useRoutes(useMemo<RouteObject[]>(()=>RegisterRouter(routes),[]))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    三、封装拦截器

    import { ReactElement } from 'react'
    import { useLocation, Navigate } from "react-router-dom";
    const whiteList:string[] = ['/login','/home','/home/homedetail']
    const Guard = ({ children }: { children: ReactElement })=>{
      const { pathname } = useLocation();
      const nextPath = onRouterBefore ? onRouterBefore(pathname) : pathname;
      if (nextPath && nextPath !== pathname) {
        children = <Navigate to='/login' replace={true}/>;
      }
      return children
    }
    /**
     *    路由拦截
     * @param pathname 跳转的路径
     */
    const onRouterBefore = (pathname:string): string => {
      console.log('路由拦截执行了')
      if(whiteList.includes(pathname)) { //  加上你的判断条件 白名单、是否登陆、是否有权限进入
        return pathname
      }
      // if return 非白名单,需要登陆的验证,可结合token、用户信息
    
       // if return router路径是否有权限进入的认证,可结合系统授权返回菜单
      return  '/login'
    }
    
    export default Guard
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    三、具体使用

    function App() {
      return (
        <Guard>
          <div className="App">
            <Link to='/home'>home</Link>
            <Link to='/about'>about</Link>
              <Outlet/>
            <!--路由注册-->
            <RouteTable/>
          </div>
        <Guard>
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    到这里不得不说,新版本的react-router@6.x又是跟vue-router是如此的像,语法思想上在不断的接近,不信看对比

    vue-routerreact-router@6.x
    router-linkLink
    router-viewOutlet
    addRoutesuseRoutes

    其余的路由拦截、路由的格式自己去凤展调用就好了,vue玩家转react可以说是成本已经很小了好吗,所以大家真的不要在乎自己用的什么技术框架,因为框架直接的习惯都在抄来抄去。只要精通一种,其他的思想都是差不多的。完毕。

  • 相关阅读:
    软考 系统架构设计师系列知识点之软件架构风格(3)
    常见的协议的协议号及端口
    Spring面试题
    Moonbeam通过新的LayerZero部署扩展跨链能力
    无线通信中CSI的含义
    物联网AI MicroPython学习之语法 I2C总线
    Golang专题——fsnotify 文件及目录监控
    SpringMVC统一异常处理配置
    九月医疗宣传日|适合幼小学宣传的几款医疗模板
    【web实现右侧弹窗】JS+CSS如何实现右侧缓慢弹窗动态效果『附完整源码下载』
  • 原文地址:https://blog.csdn.net/qq_40513881/article/details/125605225