React使用Context与router实现权限路由详细介绍
作者:绿胡子大叔
这篇文章主要介绍了React使用Context与router实现权限路由的详细过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
前言
之前使用高阶组件和Context实现简单的权限拦截,本篇文章将引入react-router
,实现权限路由功能
通过阅读本篇文章,你将了解:
- 如何在当前示例中使用
Context
,以及如何通过React Hooks
使用Context
- 创建一个
PermissionRoute
组件,强化原react-router-dom
库中的Route
组件 - 创建一个类似
react-router-config
中renderRoutes()
的函数,实现集中式权限路由配置
思路
- 创建一个高阶组件包裹根组件,使用高阶组件向根组件注入一个
Context
。此高阶组件用于保存和获取权限列表 - 通过与
Context
中的权限列表进行对比,判断是否有页面访问权限。实现渲染劫持,控制渲染路由组件或重定向组件
实现
向根组件注入权限列表
抽离Context
/* * 资源路径 ./src/utils/PermissionContext.js */ import { createContext } from "react"; const PermissionContext = createContext() export const PermissionContextProvider = PermissionContext.Provider export const PermissionContextConsumer = PermissionContext.Consumer export default PermissionContext
HOC实现
/* * 资源路径 ./src/components/PermissionIndex.js */ import React, { useState, useEffect } from 'react' import { PermissionContextProvider } from '../../utils/PermissionContext' // import对应的Context function PermissionIndex(Component) { return function Index(props){ const [permission, setpermission] = useState([]) useEffect(()=>{ setpermission(['cart']) //此处实际为 获取权限列表的请求操作 },[]) //代替了类组件的componenetDidMount生命周期 return ( <PermissionContextProvider value={permission}> <Component {...props}></Component> </PermissionContextProvider> //此处返回了注入权限列表Context的组件 ) } } export default PermissionIndex
useState
用于动态设置权限列表- 组件通过
Context.Provider
包裹。权限列表改变时,所有Context
的消费者组件更新
权限路由组件实现
实现
/* * 资源路径 ./src/components/PermissionRoute.js */ import {useContext} from "react"; import PermissionContext from "../utils/PermissionContext"; import {Redirect, Route} from "react-router-dom"; function PermissionRoute(props){ const context = useContext(PermissionContext) return ( context.indexOf(props.permission) > -1 ? <Route path={props.path} exact={props.exact} strict={props.strict} sensitive={props.sensitive} render={prop => props.render ? props.render({...prop}) : <props.component {...props}/>} /> : <Redirect from={'/props.path'} to={"/403"}/> ) } export default PermissionRoute;
- 使用
useContext
获取PermissionContext
- 利用
Array.prototype.indexOf()
方法,判断权限列表中是否存在由参数传入的权限值。若存在,则返回响应路由;若不存在,则返回Redirect
组件重定向到无权限页面
使用方法
/* * 资源路径 ./src/App.js */ import React from 'react'; import {Redirect, Route, Switch} from 'react-router-dom'; import Page1 from "./pages/Page1"; import Page2 from "./pages/Page2"; import Page3 from "./pages/Page3"; import Error from "./pages/Error"; // 无页面时显示的404页面 import PermissionIndex from "./components/PermissionIndex"; import PermissionRoute from "./components/PermissionRoute"; import NoPermission from "./pages/NoPermission"; // 无权限时显示的页面 /* * 利用es7的decorator实现高阶组件 * 此处等价于: * class App extends React.Component { * render(){} * } * const App = PermissionIndex(App) * export default App */ @PermissionIndex export default class App extends React.Component{ render() { return ( <div> <Switch> <Route path={'/page1'} component={Page1}/> <PermissionRoute path={'/page2'} component={Page2} permission={"cart"}/> <Route path={'/page3'} component={Page3}/> <Route path={'/404'} component={Error}/> <Route path={'/403'} component={NoPermission}/> <Redirect to={'/404'}/> </Switch> </div> ); } }
注意: 此处App组件已在index.js
中被BrowserRouter
组件包裹
/* * 资源路径 ./src/index.js */ import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import {BrowserRouter} from "react-router-dom"; ReactDOM.render( <React.StrictMode> <BrowserRouter> <App></App> </BrowserRouter> </React.StrictMode>, document.getElementById('root') );
实现类似react-router-config的集中式权限路由配置
实现
/* * 资源路径 ./src/components/permissionRouterConfig.js */ import {Redirect, Route, Switch} from "react-router-dom"; import React, {useContext} from "react"; import PermissionContext from "../utils/PermissionContext"; // extraParams 绑定到路由组件的其他参数 // switchParams 绑定到Switch组件的其他参数 function permissionRouterConfig(routes, extraParams = {}, switchParams = {}){ // 此处返回一个React组件,但此处不属于高阶组件 return function PRC(){ const context = useContext(PermissionContext) return routes ? ( <Switch {...switchParams}> { // 遍历传入的routes数组 routes.map((route,index)=>( /* * 通过Array.prototype.indexOf() 方法判断权限是否在权限列表中 * 通过withPermission参数判断该路由是否需要进行权限拦截 */ (context.indexOf(route.permission) > -1 || !route.withPermission) ? <Route key={route.key || index} path={route.path} exact={route.exact} sensitive={route.sensitive} strict={route.strict} render={props=>route.render?(route.render({...props, ...extraParams})) : (<route.component {...props} {...extraParams}/>)} /> : <Redirect from={route.path} to={'/403'}/> // 当权限列表中存在权限或不需要权限拦截时,渲染路由组件;否则渲染重定向组件 )) } </Switch> ) : null } } export default permissionRouterConfig
使用方法
/* * 资源路径 ./src/App.js */ import React from 'react'; import {Redirect, Route, Switch} from 'react-router-dom'; import Page1 from "./pages/Page1"; import Page2 from "./pages/Page2"; import Page3 from "./pages/Page3"; import Error from "./pages/Error"; import PermissionIndex from "./components/PermissionIndex"; import NoPermission from "./pages/NoPermission"; import permissionRouterConfig from "./components/permissionRouterConfig"; const routes = [{ path: '/page1', component: Page1, withPermission: true, // withPermission为true,启用权限拦截 permission: "cart" // 访问该页面所需的权限名 },{ path: '/page2', render: props=><Page2 {...props}></Page2> },{ path: '/page3', component: Page3, withPermission: false // withPermission为false或undefined,不启用权限拦截 },{ path: '/404', component: Error },{ path: '/403', component: NoPermission },{ path: '/', render: ()=><Redirect to={'/404'}/> }] const PermissionRouter = permissionRouterConfig(routes) // 传入routes规则,返回一个包含Switch和Route的组件 @PermissionIndex export default class App extends React.Component{ render() { return ( <div> <PermissionRouter/> </div> ); } }
到此这篇关于React使用Context与router实现权限路由详细介绍的文章就介绍到这了,更多相关React权限路由内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!