React 项目使用 TypeScript 和 Hooks API,本文介绍路由的基本配置和权鉴配置。
建立 ./src/router/index.ts 文件,配置路由路径与对应页面组件。
import { RouteConfig } from 'react-router-config';
import Login from 'src/views/Login/login';
import Home from 'src/views/Home/home';
import Welcome from 'src/views/Home/Welcome';
const routes: RouteConfig = [
{
path: '/login',
component: Login,
meta:{
name: 'login',
title: '登录'
}
},
{
path: '/home',
component: Home,
meta:{
name: 'home',
title: '主页'
}
routes: [
{
path: '/home/welcome',
component: Welcome,
meta:{
name: 'welcome',
active: 'welcome',
title: '欢迎页面'
}
},
]
}
]
export default routes;
./src/model/route.ts 这里集中定义了路由组件的接口类型
import { FC } from 'react';
interface IMeta {
name: string;
active?: string;
title?: string;
}
interface routeInterface {
path: string;
component: FC;
meta?: IMeta;
redirect?: string;
auth?: boolean;
routes?: Array<any>;
}
export type RouteInterface = routeInterface
./src/app.tsx 修改路由相关
import { FC, useReducer } from 'react';
import { BrowserRouter as Router, Redirect, Switch } from 'react-router-dom';
import routes from 'src/router';
import RouteWithSubRoutes from 'src/components/route';
import { RouteInterface } from 'src/model/route';
const App: FC = () => {
return (
...
<Router>
<Switch>
<Redirect exact from="/" to="/login" />
{routes.map((route: RouteInterface, i: number) => {
return RouteWithSubRoutes(route, i)
})}
</Switch>
</Router>
...
)
}
export default App;
- ./src/app.tsx 只列出与路由相关代码,
- <Switch> 中先定义 <Redirect> 重定向默认跳转到登录页。
- 这里定义了一个路由组件 RouteWithSubRoutes 重定向之后,遍历之前定义的 ./src/router/index.ts 路由配置文件,并输出这个路由组件返回的内容。
./src/components/route.tsx 即刚定义的 RouteWithSubRoutes 组件。
import { Route, Redirect } from 'react-router-dom';
import { RouteInterface } from 'src/model/route';
const RouteWithSubRoutes = (route: RouteInterface, index: number ) => {
return (
<Route
key={index}
path={route.path}
render={props =>
<route.component {...props} routes={route.routes} />
}
/>
);
}
export default RouteWithSubRoutes
如此,简单的路由配置好了,启动项目默认跳转到登录页 /login,如果访问 /home/welcome 就直接跳转到登录之后的欢迎页。
现在要给路由加权鉴,简单点的需求是让登录页不设权鉴,而让登录后 /home 相关的所有子路由都加上权鉴,并根据登录状态判断能否访问。
修改一下 ./src/router/index.ts 文件
...
const routes: RouteConfig = [
{
path: '/login',
component: Login,
meta:{
name: 'login',
title: '登录'
},
auth: false
},
{
path: '/home',
component: Home,
meta:{
name: 'home',
title: '主页'
},
auth: true,
routes: [
{
path: '/home/welcome',
component: Welcome,
meta:{
name: 'welcome',
active: 'welcome',
title: '欢迎页面'
},
auth: true
},
]
}
]
export default routes;
- 给每个路由和子路由加上 auth , true 代表有权鉴,false 代表没有。
修改 ./src/components/route.tsx
import { Route, Redirect } from 'react-router-dom';
import { RouteInterface } from 'src/model/route';
import { renderRoutes } from 'react-router-config';
import store from 'src/store';
// 渲染结果
const myRender = ( route:RouteInterface, index:number, props:any ) => {
let token = store.getState().user || null;
// 登录状态
if( token ){
// 已登录状态跳转到登录页
if ( route.auth ) {
console.log('已登录,有权鉴');
return <route.component items={route} {...props} routes={route.routes} />
} else {
console.log('已登录,没有权鉴');
return <Redirect to={{ pathname:'/home' }} />
}
} else {
// 非登录状态下,通过权鉴时
if ( route.auth ) {
console.log('非登录状态下,通过权鉴时');
return (
<Redirect exact to={{ pathname: '/login' }} />
);
} else {
console.log('非登录状态下,没通过权鉴时');
return <route.component {...props} routes={renderRoutes(route.routes)} />
}
}
}
const RouteWithSubRoutes = (route: RouteInterface, index: number ) => {
return (
<Route
key={index}
path={route.path}
render={props =>
myRender(route,index,props)
}
/>
);
}
export RouteWithSubRoutes
- 把渲染部分独立成 myRender 方法
- 首先通过 token 判断登录状态,分别在登录和没登录两个逻辑中再次通过 auth 判断有无权鉴。
- 在非登录状态访问有权鉴的页面会跳到登录页。
- 在非登录状态访问没权鉴的页面,好像只有登录页符合这样的条件。
- 登录状态访问有权鉴的页面正常返回子路由组件。
- 登录状态访问没权鉴的页面,可以定义个 404 页面并返回,我这里只重定向到 ./home 路由。
至此,权鉴添加完毕。