实际开发中,我们仍然希望看到是一个路由的JSON体,能很清楚的了解整个路由结构,在react中有点不一样的是需要循环出路由组件,并在全局中使用。所以我们可以自己建立一个JSON体用来循环数据,达到我们想要的效果,有时涉及到权限管理时,常见的像后台应用,我们也可以根据请求结果的JSON进行循环,区别无疑是本地和非本地而已。
如果是接口请求来的,可以结合store保留接口请求过来的menu的菜单list,顺便做个持久化存储
剩下的那我们就要保证路由与本地目录是完全匹配的,通过一次性的递归,动态匹配router与component并生成如下图的格式,或者以下图格式为global路由在此基础上进行数组合并:
这里通过useRoutes
hook注册了路由组件,利用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),[]))
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
function App() {
return (
<Guard>
<div className="App">
<Link to='/home'>home</Link>
<Link to='/about'>about</Link>
<Outlet/>
<!--路由注册-->
<RouteTable/>
</div>
<Guard>
);
}
到这里不得不说,新版本的react-router@6.x
又是跟vue-router
是如此的像,语法思想上在不断的接近,不信看对比
vue-router | react-router@6.x |
---|---|
router-link | Link |
router-view | Outlet |
addRoutes | useRoutes |
其余的路由拦截、路由的格式自己去凤展调用就好了,vue玩家转react可以说是成本已经很小了好吗,所以大家真的不要在乎自己用的什么技术框架,因为框架直接的习惯都在抄来抄去。只要精通一种,其他的思想都是差不多的。完毕。