網(wǎng)站首頁 編程語言 正文
前言
之前使用高階組件和Context實(shí)現(xiàn)簡單的權(quán)限攔截,本篇文章將引入react-router
,實(shí)現(xiàn)權(quán)限路由功能
通過閱讀本篇文章,你將了解:
- 如何在當(dāng)前示例中使用
Context
,以及如何通過React Hooks
使用Context
- 創(chuàng)建一個(gè)
PermissionRoute
組件,強(qiáng)化原react-router-dom
庫中的Route
組件 - 創(chuàng)建一個(gè)類似
react-router-config
中renderRoutes()
的函數(shù),實(shí)現(xiàn)集中式權(quán)限路由配置
思路
- 創(chuàng)建一個(gè)高階組件包裹根組件,使用高階組件向根組件注入一個(gè)
Context
。此高階組件用于保存和獲取權(quán)限列表 - 通過與
Context
中的權(quán)限列表進(jìn)行對比,判斷是否有頁面訪問權(quán)限。實(shí)現(xiàn)渲染劫持,控制渲染路由組件或重定向組件
實(shí)現(xiàn)
向根組件注入權(quán)限列表
抽離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實(shí)現(xiàn)
/* * 資源路徑 ./src/components/PermissionIndex.js */ import React, { useState, useEffect } from 'react' import { PermissionContextProvider } from '../../utils/PermissionContext' // import對應(yīng)的Context function PermissionIndex(Component) { return function Index(props){ const [permission, setpermission] = useState([]) useEffect(()=>{ setpermission(['cart']) //此處實(shí)際為 獲取權(quán)限列表的請求操作 },[]) //代替了類組件的componenetDidMount生命周期 return ( <PermissionContextProvider value={permission}> <Component {...props}></Component> </PermissionContextProvider> //此處返回了注入權(quán)限列表Context的組件 ) } } export default PermissionIndex
-
useState
用于動(dòng)態(tài)設(shè)置權(quán)限列表 - 組件通過
Context.Provider
包裹。權(quán)限列表改變時(shí),所有Context
的消費(fèi)者組件更新
權(quán)限路由組件實(shí)現(xiàn)
實(shí)現(xiàn)
/* * 資源路徑 ./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()
方法,判斷權(quán)限列表中是否存在由參數(shù)傳入的權(quán)限值。若存在,則返回響應(yīng)路由;若不存在,則返回Redirect
組件重定向到無權(quán)限頁面
使用方法
/* * 資源路徑 ./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"; // 無頁面時(shí)顯示的404頁面 import PermissionIndex from "./components/PermissionIndex"; import PermissionRoute from "./components/PermissionRoute"; import NoPermission from "./pages/NoPermission"; // 無權(quán)限時(shí)顯示的頁面 /* * 利用es7的decorator實(shí)現(xiàn)高階組件 * 此處等價(jià)于: * 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') );
實(shí)現(xiàn)類似react-router-config的集中式權(quán)限路由配置
實(shí)現(xiàn)
/* * 資源路徑 ./src/components/permissionRouterConfig.js */ import {Redirect, Route, Switch} from "react-router-dom"; import React, {useContext} from "react"; import PermissionContext from "../utils/PermissionContext"; // extraParams 綁定到路由組件的其他參數(shù) // switchParams 綁定到Switch組件的其他參數(shù) function permissionRouterConfig(routes, extraParams = {}, switchParams = {}){ // 此處返回一個(gè)React組件,但此處不屬于高階組件 return function PRC(){ const context = useContext(PermissionContext) return routes ? ( <Switch {...switchParams}> { // 遍歷傳入的routes數(shù)組 routes.map((route,index)=>( /* * 通過Array.prototype.indexOf() 方法判斷權(quán)限是否在權(quán)限列表中 * 通過withPermission參數(shù)判斷該路由是否需要進(jìn)行權(quán)限攔截 */ (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'}/> // 當(dāng)權(quán)限列表中存在權(quán)限或不需要權(quán)限攔截時(shí),渲染路由組件;否則渲染重定向組件 )) } </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,啟用權(quán)限攔截 permission: "cart" // 訪問該頁面所需的權(quán)限名 },{ path: '/page2', render: props=><Page2 {...props}></Page2> },{ path: '/page3', component: Page3, withPermission: false // withPermission為false或undefined,不啟用權(quán)限攔截 },{ path: '/404', component: Error },{ path: '/403', component: NoPermission },{ path: '/', render: ()=><Redirect to={'/404'}/> }] const PermissionRouter = permissionRouterConfig(routes) // 傳入routes規(guī)則,返回一個(gè)包含Switch和Route的組件 @PermissionIndex export default class App extends React.Component{ render() { return ( <div> <PermissionRouter/> </div> ); } }
原文鏈接:https://blog.csdn.net/m0_52761633/article/details/123824002
相關(guān)推薦
- 2022-05-20 子查詢關(guān)鍵字-ALL、ANY、SOME、IN、EXISTS
- 2022-11-15 Flutter異步操作實(shí)現(xiàn)流程詳解_Android
- 2022-01-10 egg作為后端接口,在前端調(diào)用
- 2023-03-03 Fragment通過FragmentManager實(shí)現(xiàn)通信功能詳細(xì)講解_Android
- 2022-06-07 ASP.NET?Core應(yīng)用啟動(dòng)Startup類簡介_基礎(chǔ)應(yīng)用
- 2022-03-08 使用C語言實(shí)現(xiàn)本地socke通訊的方法_C 語言
- 2022-05-25 Flutter實(shí)現(xiàn)倒計(jì)時(shí)功能_Android
- 2022-11-10 Linux實(shí)現(xiàn)壓縮文件的生成與查看的常用命令總結(jié)_linux shell
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支