1、创建文件
我们在 /src/router 目录中创建一个 RouterGuards.jsx 文件作为导航守卫的配置文件。
然后在 src 目录中新建一个 config 的目录,然后在该目录中创建一个 routes.js 文件,用来设置项目中涉及到路由相关数据。
2、配置一级路由数据
我们首先先来处理用户是否登录的权限问题。
我们在 routes.js 文件中添加项目中所有一级路由相关的数据:
import Login from "../pages/login/Login"
import Register from "../pages/register/Register"
import Home from "../pages/home/Home"
const routes = [
{ path: '/login', component: Login },
{ path: '/register', component: Register },
{ path: '/404', component: NotFound },
{ path: '/', component: Home, isLogin: true }
]
export default routes;
其中,isLogin: true 属性用来表示当前路由需要登录才能访问。
3、渲染一级路由,处理 404
在 RouterGuards.jsx 文件中,渲染一级路由的配置:
- 获取用户访问的路径;
- 然后判断用户访问的路径在项目中是否存在;
- 如果存在,则生成当前路由的配置代码;
- 如果不存在,则直接重定向到 404 页面;
import React from 'react'
import { Redirect, Route, useLocation } from 'react-router-dom';// 项目中所有的路由数据import routes from '../config/routes'
export default function RouterGuards() { // 1. 获取当前用户访问的路由地址
const location = useLocation();
const userPath = location.pathname;
// 2. 判断当前用户访问的路由地址在项目中是否存在
const userRoute = routes. find(item => item.path === userPath);
if (userRoute) {
// 3. 进入 if,则表示用户访问的路由是项目中存在的路由
return <Route path={userRoute.path} component={userRoute.component}></Route>
} else {
// 4. 进入 else,则表示用户访问的路由在项目中不存在
return <Redirect to="/404"></Redirect>
}
}
然后在 RootRouter.jsx 中引入该配置组件:
export default function RootRouter() {
return (
<React.Suspense fallback={<h1>加载中...</h1>}>
<BrowserRouter>
<Switch>
<RouterGuards></RouterGuards>
</Switch>
</BrowserRouter>
</React.Suspense>
)
}
4、处理未登录访问路由
export default function RouterGuards() {
// 1. 获取当前用户访问的路由地址
const location = useLocation();
const userPath = location.pathname;
// 2. 判断当前用户访问的路由地址在项目中是否存在
const userRoute = routes.find(item => item.path === userPath);
if (userRoute) {
// 3. 进入 if,则表示用户访问的路由是项目中存在的路由
if (userRoute.isLogin) {
// 6. 进入 if,说明用户当前访问的路由需要登录
// 7. 判断用户是否登录(实际开发中,应该还需要发送请求验证 token 是否过期)
const token = localStorage.token;
if (token) {
// 8. 进入 if,说明用户登录了,可以让用户去到想要访问的路由
return <Route path={userRoute.path} component={userRoute.component}></Route> }
// 9. 说明当前路由需要登录,但是用户没有登录
return <Redirect to="/login"></Redirect>
}
// 10. 当前用户访问的路由存在,且不需要登录
return <Route path={userRoute.path} component={userRoute.component}></Route>
} else {
// 4. 进入 else,则表示用户访问的路由在项目中不存在
return <Redirect to="/404"></Redirect>
}
}
5、配置二级路由数据
const routes = [
{ path: '/login', component: Login },
{ path: '/register', component: Register },
{ path: '/404', component: NotFound },
{ path: '/', component: Home, isLogin: true, },
{ path: '/main', component: Home, isLogin: true, },
{ path: '/users', component: Home, isLogin: true, },
{ path: '/roles', component: Home, isLogin: true, },
{ path: '/products/categories', component: Home, isLogin: true, },
{ path: '/products/list', component: Home, isLogin: true },
{ path: '/products/add', component: Home, isLogin: true },
{ path: '/products/update', component: Home, isLogin: true },
{ path: '/finances/payment', component: Home, isLogin: true },
{ path: '/finances/sales', component: Home, isLogin: true }
]
6、渲染二级路由的父路由
import React from 'react'import { Redirect, Route, useLocation } from 'react-router-dom';
import { message } from 'antd';// 项目中所有的路由数据
import routes from '../config/routes'
export default function RouterGuards() {
// 1. 获取当前用户访问的路由地址
const location = useLocation();
const userPath = location.pathname;
// 2. 判断当前用户访问的路由地址在项目中是否存在
const userRoute = routes.find(item => item.path === userPath);
if (userRoute) {
// 3. 进入 if,则表示用户访问的路由是项目中存在的路由
// 5. 判断当前路由是否需要用户登录后才能访问
if (userRoute.isLogin) {
// 6. 进入 if,说明用户当前访问的路由需要登录
// 7. 判断用户是否登录(实际开发中,应该还需要发送请求验证 token 是否过期) const token = localStorage.token;
if (token) {
// 8. 进入 if,说明用户登录了,可以让用户去到想要访问的路由
// 当代码执行到这一步时,针对当前项目,说明当前用户访问的路径,要么是 /,那么就是 / 的子路由 // 11. 判断当前用户是否有权限访问当前路由
// 12. 获取用户能够访问的路由的数据
const roleMenus = JSON.parse(localStorage.menus || '[]');
// 13. 判断当前用户访问的路径是否在 roleMenus 数组中
if (roleMenus.includes(userPath) || userPath === '/') {
return <Route path="/" component={userRoute.component}></Route>
}
// 14. 用户没有权限访问当前路径
return <Redirect to="/404"></Redirect>
}
// 9. 说明当前路由需要登录,但是用户没有登录
return <Redirect to="/login"></Redirect>
}
// 10. 当前用户访问的路由存在,且不需要登录
return <Route path={userRoute.path} component={userRoute.component}></Route>
} else {
// 4. 进入 else,则表示用户访问的路由在项目中不存在
return <Redirect to="/404"></Redirect>
}
}
7、处理动态路由
export default function RouterGuards() {
// ...
// 2. 判断当前用户访问的路由地址在项目中是否存在
const userRoute = routes.find(item => {
if (item.path === '/products/update') {
return userPath.includes(item.path);
}
return item.path === userPath;
});
// ...
// 13. 判断当前用户访问的路径是否在 roleMenus 数组中
if (roleMenus.includes(userPath) || userPath === '/' || userPath.includes('/products/update/')) {
return <Route path="/" component={userRoute.component}></Route>
}
}