react-router-config
Static route config helpers
使用
需要注意的是,在page2中, renderRoutes(routes)
的routes是在props中获取的,即应该写成renderRoutes(props.route.routes)
import React from "react";
import { renderRoutes } from "react-router-config";
import { HashRouter, Redirect } from "react-router-dom";
const routes = [
{ path: "/", exact: true, render: () => <Redirect to={"/page1"} /> },
{ path: "/page1", component: Page1 },
{
path: "/page2",
component: Page2,
routes: [
{
path: "/page2/child",
component: Child
}
]
}
];
function App() {
return (
<HashRouter>
<div className="App">
<h1>Hello</h1>
{renderRoutes(routes)}
</div>
</HashRouter>
);
}
renderRoutes源码
其实就是把routes做了个map。根据源码,就很容易做个类似vue的路由守卫了。
import React from "react";
import { Switch, Route } from "react-router";
function renderRoutes(routes, extraProps = {}, switchProps = {}) {
return routes ? (
<Switch {...switchProps}>
{routes.map((route, i) => (
<Route
key={route.key || i}
path={route.path}
exact={route.exact}
strict={route.strict}
render={props =>
route.render ? (
route.render({ ...props, ...extraProps, route: route })
) : (
<route.component {...props} {...extraProps} route={route} />
)
}
/>
))}
</Switch>
) : null;
}
export default renderRoutes;
路由鉴权
以下是个人重写,添加了多重权限验证以及多重路由匹配(即添加渲染非<Switch>
包裹的<Route>
)。
export interface IRouteConfig extends RouteConfig {
auth?: number;
routes?: IRouteConfig[];
multipleRoutes?: IRouteConfig[];
}
/**
* 将路由配置渲染成节点
* @param routes switch路由列表
* @param authed 当前账号权限
* @param multipleRoutes 非switch路由列表,将会在Switch节点前渲染Route
* @param extraProps 添加额外的Route props
* @param switchProps Switch props
*/
function renderRoutes(
routes: IRouteConfig[] | undefined,
authed: number,
multipleRoutes?: IRouteConfig[],
extraProps?: any,
switchProps?: SwitchProps
) {
const isMobile = checkMobile();
let list = [];
const mapFunc = (R: IRouteConfig[]) =>
R.map((route, i) => (
<Route
key={route.key || i}
path={route.path}
exact={route.exact}
strict={route.strict}
render={props => {
// 将authed赋值到route,试子组件可以通过route.authed获取当前用户权限
if (authed !== undefined) route.authed = authed;
// 不存在authed或者authed大于当前路由权限,即可渲染组件,否则跳转登录界面
if (!route.auth || route.auth <= authed) {
return route.render
? route.render({ ...props, ...extraProps, route: route })
: route.component && (
<route.component {...props} {...extraProps} route={route} />
);
} else {
message.warn("请先登录!");
return (
<Redirect to={route.auth <= 1 "/user/loginRegister/login"} />
);
}
}}
/>
));
if (routes) {
list.push(
<Switch {...switchProps} key="biubiubiu~~">
{mapFunc(routes)}
</Switch>
);
// 将非Switch包裹的Route挂载到Switch节点之前
multipleRoutes && list.unshift(...mapFunc(multipleRoutes));
// 返回一个数组,[<Route/>,...,<Route/>,<Switch>...</Switch>](实际元素并非如此结构,此处仅为方便说明写的伪代码),React会将数组渲染成节点
return list;
}
}
修改后的routes,当匹配到"/user/all/article/(id值)"
的路径,页面会同时渲染Article以及All两个组件,未登录则渲染Article和Login组件,mutipleRoutes
主要是为了能通过多重匹配路由模拟VUE的keep-alive
效果。代码如下👇:
export const mobileRouterList: IRouteConfig[] = [
{
path: "/",
exact: true,
render: () => <Redirect to="/user/all" />
},
{
path: "/user",
component: MobileMain,
multipleRoutes: [
{ path: "/user/:page/article/:id", component: Article }
],
routes: [
{
path: "/user/all",
component: lazy(() => import("@/pages/user/All"))
},
{
path: "/user/me",
auth: 1, // 用户权限必须 >=1 才可以访问
component: lazy(() => import("@/pages/user/Me"))
},
{
path: "/admin/controlPanel",
auth: 2, // 用户权限必须 >=2(管理员) 才可以访问
component: lazy(() => import("@/pages/admin/ControlPanel"))
}
]
}
]
修改后的rednerRoutes使用,后面参数选填:
// 顶层使用路由渲染,手动添加第二参数
renderRoutes(routes,user.authed)
// 子层组件路由渲染
renderRoutes(props.route.routes,<props.route.authed>,<props.route.multipleRoutes>,...)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。