React使用Context與router實(shí)現(xiàn)權(quán)限路由詳細(xì)介紹
前言
之前使用高階組件和Context實(shí)現(xiàn)簡(jiǎn)單的權(quán)限攔截,本篇文章將引入react-router
,實(shí)現(xiàn)權(quán)限路由功能
通過(guò)閱讀本篇文章,你將了解:
- 如何在當(dāng)前示例中使用
Context
,以及如何通過(guò)React Hooks
使用Context
- 創(chuàng)建一個(gè)
PermissionRoute
組件,強(qiáng)化原react-router-dom
庫(kù)中的Route
組件 - 創(chuàng)建一個(gè)類似
react-router-config
中renderRoutes()
的函數(shù),實(shí)現(xiàn)集中式權(quán)限路由配置
思路
- 創(chuàng)建一個(gè)高階組件包裹根組件,使用高階組件向根組件注入一個(gè)
Context
。此高階組件用于保存和獲取權(quán)限列表 - 通過(guò)與
Context
中的權(quán)限列表進(jìn)行對(duì)比,判斷是否有頁(yè)面訪問(wè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對(duì)應(yīng)的Context function PermissionIndex(Component) { return function Index(props){ const [permission, setpermission] = useState([]) useEffect(()=>{ setpermission(['cart']) //此處實(shí)際為 獲取權(quán)限列表的請(qǐng)求操作 },[]) //代替了類組件的componenetDidMount生命周期 return ( <PermissionContextProvider value={permission}> <Component {...props}></Component> </PermissionContextProvider> //此處返回了注入權(quán)限列表Context的組件 ) } } export default PermissionIndex
useState
用于動(dòng)態(tài)設(shè)置權(quán)限列表- 組件通過(guò)
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
組件重定向到無(wú)權(quán)限頁(yè)面
使用方法
/* * 資源路徑 ./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"; // 無(wú)頁(yè)面時(shí)顯示的404頁(yè)面 import PermissionIndex from "./components/PermissionIndex"; import PermissionRoute from "./components/PermissionRoute"; import NoPermission from "./pages/NoPermission"; // 無(wú)權(quán)限時(shí)顯示的頁(yè)面 /* * 利用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)=>( /* * 通過(guò)Array.prototype.indexOf() 方法判斷權(quán)限是否在權(quán)限列表中 * 通過(guò)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" // 訪問(wèn)該頁(yè)面所需的權(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> ); } }
到此這篇關(guān)于React使用Context與router實(shí)現(xiàn)權(quán)限路由詳細(xì)介紹的文章就介紹到這了,更多相關(guān)React權(quán)限路由內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react頁(yè)面中存在多個(gè)input時(shí)巧妙設(shè)置value屬性方式
這篇文章主要介紹了react頁(yè)面中存在多個(gè)input時(shí)巧妙設(shè)置value屬性方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05React自定義hooks同步獲取useState的最新?tīng)顟B(tài)值方式
這篇文章主要介紹了React自定義hooks同步獲取useState的最新?tīng)顟B(tài)值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03使用React hook實(shí)現(xiàn)remember me功能
相信大家在使用 React 寫(xiě)頁(yè)面的時(shí)候都遇到過(guò)完成 Remember me 的需求吧!本文就將這個(gè)需求封裝在一個(gè) React hook 中以供后續(xù)的使用,覺(jué)得有用的同學(xué)可以收藏起來(lái)以備不時(shí)之需,感興趣的小伙伴跟著小編一起來(lái)看看吧2024-04-04從零開(kāi)始學(xué)習(xí)搭建React腳手架項(xiàng)目
這篇文章主要介紹了從零開(kāi)始學(xué)習(xí)搭建React腳手架項(xiàng)目,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08react-native中ListView組件點(diǎn)擊跳轉(zhuǎn)的方法示例
ListView作為React Native的核心組件,用于高效地顯示一個(gè)可以垂直滾動(dòng)的變化的數(shù)據(jù)列表。下面這篇文章主要給大家介紹了關(guān)于react-native中ListView組件點(diǎn)擊跳轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-09-09