react路由守衛的實現(路由攔截)
react不同於vue,通過在路由裡設置meta元字符實現路由攔截。在使用 Vue ,框架提供瞭路由守衛功能,用來在進入某個路有前進行一些校驗工作,如果校驗失敗,就跳轉到 404 或者登陸頁面,比如 Vue 中的 beforeEnter 函數:
... router.beforeEach(async(to, from, next) => { const toPath = to.path; const fromPath = from.path; }) ...
react實現路由攔截的基本思路還是利用Route 的render函數。通過判斷攔截條件來實現不同的組件的跳轉,從而實現攔截。在之前的版本中,React Router 也提供瞭類似的 onEnter 鉤子,但在 React Router 4.0 版本中,取消瞭這個方法。React Router 4.0 以後采用瞭聲明式的組件,路由即組件,要實現路由守衛功能,就得我們自己去寫瞭。
如果不使用路由守衛,Router 組件是這樣子的:
import * as React from 'react'; import { HashRouter,Switch,Route,Redirect } from 'react-router-dom'; import Index from "./page/index"; import Home from "./page/home"; import ErrorPage from "./page/error"; import Login from "./page/login"; export const Router = () => ( <HashRouter> <Switch> <Route path="/" exact component={Index}/> <Route path="/login" exact component={Login}/> <Route path="/home" exact component={Home}/> <Route path="/404" exact component={ErrorPage}/> <Redirect to="/404" /> </Switch> </HashRouter> );
上面的 Router 組件,包含瞭三個頁面:
登陸
主頁
404 頁面
以及四個路由:
根路由
登陸路由
主頁路由
404 路由
其中,根路由和 /home 路由,都定向到瞭主頁路由。
以上是一個基本的路由定義,可以在登陸/主頁和 404 頁面之間來回跳轉,但也有一些問題:
非登陸狀態下,可以直接跳轉到主頁
登陸狀態下,也可以輸入 /login 路由跳轉到登錄頁
現在,我們想完成這樣的功能:
非登陸狀態下,無法直接跳轉到主頁,如果在非登陸狀態下進行主頁跳轉,需要重定向至登陸路由
登陸狀態下,無法跳轉至登錄頁,如果在登陸狀態下進行登陸頁跳轉,需要重定向至主頁路由
要完成這個功能,有兩種方案:
在每個組件中,根據 props 上的 history 對象來進行跳轉
進行全局的路由守衛處理
首先在跟目錄src下創建一個routerMap.js文件,代碼如下:
將 auth 設置為 true,表示該路由需要權限校驗。
/** * 定義路由組件,將 auth 設置為 true,表示該路由需要權限校驗 */ import Admin from "./pages/Admin"; import Login from "./pages/Login"; import Error from "./pages/Error"; export const routerMap = [ {path: "/", name: "admin", component: Admin, auth: true}, {path: "/login", name: "Login", component: Login}, {path: "/error", name: "error", component: Error}, ];
所有的路由跳轉,都交給 FrontendAuth 高階組件代理完成。下面是 FrontendAuth.js 組件的實現:
/** * 路由守衛校驗 */ import React, {Component} from "react"; import {Route, Redirect} from "react-router-dom"; class FrontendAuth extends Component { // eslint-disable-next-line no-useless-constructor constructor(props) { super(props); } render() { const {routerConfig, location} = this.props; const {pathname} = location; const isLogin = localStorage.getItem("user"); console.log(pathname, isLogin); console.log(location); // 如果該路由不用進行權限校驗,登錄狀態下登陸頁除外 // 因為登陸後,無法跳轉到登陸頁 // 這部分代碼,是為瞭在非登陸狀態下,訪問不需要權限校驗的路由 const targetRouterConfig = routerConfig.find( (item) => item.path === pathname ); console.log(targetRouterConfig); if (targetRouterConfig && !targetRouterConfig.auth && !isLogin) { const {component} = targetRouterConfig; return <Route exact path={pathname} component={component}/>; } if (isLogin) { // 如果是登陸狀態,想要跳轉到登陸,重定向到主頁 if (pathname === "/login") { return <Redirect to="/"/>; } else { // 如果路由合法,就跳轉到相應的路由 if (targetRouterConfig) { return ( <Route path={pathname} component={targetRouterConfig.component}/> ); } else { // 如果路由不合法,重定向到 404 頁面 return <Redirect to="/error"/>; } } } else { // 非登陸狀態下,當路由合法時且需要權限校驗時,跳轉到登陸頁面,要求登陸 if (targetRouterConfig && targetRouterConfig.auth) { return <Redirect to="/login"/>; } else { // 非登陸狀態下,路由不合法時,重定向至 404 return <Redirect to="/error"/>; } } } } export default FrontendAuth;
然後,定義 Router 組件,在App.js中,該組件是經過高階組件包裝後的結果:
import './App.less'; import React, {Fragment} from "react"; import {Switch} from 'react-router-dom' import FrontendAuth from "./FrontendAuth"; import {routerMap} from "./routerMap"; function App() { return ( <Fragment> {/*隻匹配一個,匹配成功就不往下匹配,效率高*/} <Switch> <FrontendAuth routerConfig={routerMap}/> </Switch> </Fragment> ); } export default App;
測試
到此這篇關於react路由守衛的實現(路由攔截)的文章就介紹到這瞭,更多相關react路由守衛內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 五分鐘教你瞭解一下react路由知識
- React組件通信之路由傳參(react-router-dom)
- React-Router6版本的更新引起的路由用法變化
- React中路由參數如何改變頁面不刷新數據的情況
- react 路由Link配置詳解