在Vue和Umi中都有集成预置的路由集中配置与鉴权,非常的方便好用;但是在默认React项目中是编程式路由,将需要手动进行配置式路由构建与权限构建;RouterV6中提供了一个与(router-view)具有相同功能的(Outlet)组件,可以直接给子路由指定出口位置,那么我们就可以实现一个类似Vue一样的路由;
(1)安装 npm i [email protected]
(2)src目录下建一个Router文件夹,内部创建一个routerConfig.tsx文件;
(3)进行路由懒加载;
import Loadable from "react-loadable";
const LoadingTip = () => 加载路由ing...;
const Login = Loadable({
loader: () => import("@/pages/rootLevelPages/login/Login"),
loading: LoadingTip,
});
(4)指定路由结构;
export type RoutesItems = {
path: string;
element: React.ReactElement;
children?: RoutesItems[];
};
(5)配置路由表(注意element后面需要写成<.../>形式);
export const rootRouterConfig:RoutesItems[] = [
{
path: "/",
element: ,
},
{
path: "login",
element: ,
},
{
path: "home",
element: ,
children: [
{
path: "*",
element: ,
},
{
path: "userManage/userPassword",
element: ,
children: [
{ path: "change", element: 修改密码页面
},
{ path: "reset", element: 重置密码页面
},
{ path: "fingerprint", element: 指纹密码页面
},
],
},
{
path: "userManage/userInfo",
element: ,
children: [
{
path: "detail:id",
element: ,
},
{
path: "avator:id",
element: ,
},
],
},
{
path: "computerManage/computerInfo",
element: ,
},
{
path: "computerManage/computerDevice",
element: ,
},
{
path: "notifyManage/notifyInfo",
element: ,
},
{
path: "notifyManage/notifyData",
element: ,
},
{ path: "*", element: ERROR-PAGE
},
],
},
{ path: "*", element: ERROR-PAGE;
},
{ path: "error", element: ERROR-PAGE-对不起-您没有该路由权限;
},
];
如果是直接配置路由组件是写成这种结构,是可以直接进行内部嵌套,也就是父子路由,那么就可以给子路由制定Outlet出口;
}>
} />
} />
注意path是可以不用"/"链接父子路径的,会自动处理;
最后会访问home/userManage/userPassword对应的组件;
(6)这个时候我们有了Config就只需要将它渲染成上面的这种嵌套结构即可;
使用一个小递归进行处理:
const renderRoutes = (routes: RoutesItems[]) => {
return routes.map((item: RoutesItems, index: number) => {
if (item && item.children) {
return (
{renderRoutes(item.children)}
);
} else {
return (
);
}
});
};
return (
<>
{renderRoutes(rootRouterConfig)}
>
);
(7)在父级组件 中指定Outlet给予子路由出口;
//子路由显示在此处;
现在就已经实现了配置式路由,可以很方便的操作RouterConfig就行了,其它的事情可以不用关心了;
当然也可以直接使用V6自带的useRoutes()API;这样写可以获得更多扩展性;
(8)路由鉴权,RouterV6中通过useLocation可以获取到当前路由地址,我们再写一个自定义的验证Hook比对其进行拦截;
例如通过一个请求Api获得当前用户的路由权限列表,赋值给Context;
const { state, dispatch } = useContext(ContentContext);
useEffect(() => {
dispatch({type:"userRouterPermissions",payload:['/home/computerManage/computerInfo','/home/userManage/userPassword']});
}, []);
注意防止强刷需要在App.js中进行获取;
(9)封装一个自定义验证hook;
import { ContentContext } from "@/context/ContextProvider";
import { useContext } from "react";
export default function useRouterAuth(currentPathname:string) {
const { state } = useContext(ContentContext);
console.log("登陆账号路由权限列表", state.routerPermissions,"当前进入的路由地址",currentPathname);
const AuthResult: boolean = state.routerPermissions.find(
(x: string) => x === currentPathname
)
? true
: false;
return {
AuthResult,
};
}
(10)在访问页面中进行调用;
let navigate = useNavigate();
let location = useLocation();
const { AuthResult } = useRouterAuth(location.pathname);
if (!AuthResult) {
navigate("/error");
}