React Router 4.0 实现路由守卫
在使用 Vue 或者 Angular 的时候,框架提供了路由守卫功能,用来在进入某个路有前进行一些校验工作,如果校验失败,就跳转到 404 或者登陆页面,比如 Vue 中的 beforeEnter 函数:
...
router.beforeEach(async(to, from, next) => {
const toPath = to.path;
const fromPath = from.path;
})
...
在之前的版本中,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 { HomePage } from '../pages/home/home.page';
import { LoginPage } from '../pages/login/login.page';
import { ErrorPage } from '../pages/error/error.page';
export const Router = () => (
<HashRouter>
<Switch>
<Route path="/" exact component={HomePage}/>
<Route path="/login" exact component={LoginPage}/>
<Route path="/home" exact component={HomePage}/>
<Route path="/404" exact component={ErrorPage}/>
<Redirect to="/404" />
</Switch>
</HashRouter>
);
上面的 Router 组件,包含了三个页面:
- 登陆
- 主页
- 404 页面
以及四个路由:
- 根路由
- 登陆路由
- 主页路由
- 404 路由
其中,根路由和 /home 路由,都定向到了主页路由。
以上是一个基本的路由定义,可以在登陆/主页和 404 页面之间来回跳转,但也有一些问题:
- 非登陆状态下,可以直接跳转到主页
- 登陆状态下,也可以输入
/login路由跳转到登录页
现在,我们想完成这样的功能:
- 非登陆状态下,无法直接跳转到主页,如果在非登陆状态下进行主页跳转,需要重定向至登陆路由
- 登陆状态下,无法跳转至登录页,如果在登陆状态下进行登陆页跳转,需要重定向至主页路由
要完成这个功能,有两种方案:
- 在每个组件中,根据
props上的history对象来进行跳转 - 进行全局的路由守卫处理
第一种方式,实现起来比较简单,但有很多的代码量,这里主要介绍第二种方式。
在 React Router 4.0 中,没有再像之前的版本那样,提供 onEnter 这样的全局跳转钩子,因此要通过高阶组件的方式去处理。
下面是我的实现方式,首先,准备一份路由表,包含了路由的地址,组件以及是否需要权限校验:
import { HomePage } from '../pages/home/home.page';
import { LoginPage } from '../pages/login/login.page';
import { ErrorPage } from '../pages/error/error.page';
interface routerConfigModel {
path:string,
component?:any,
auth?:boolean
}
export const routerConfig:routerConfigModel[] = [
{
path:'/',
component:HomePage,
auth:true,
},{
path:'/home',
component:HomePage,
auth:true,
},{
path:'/login',
component:LoginPage,
},{
path:'/404',
component:ErrorPage
}
];
将 auth 设置为 true,表示该路由需要权限校验。
然后,定义 Router 组件,该组件是经过高阶组件包装后的结果:
import * as React from 'react';
import { HashRouter,Switch } from 'react-router-dom';
import { FrontendAuth } from '../components/frontend-auth/frontend-auth.component'
import { routerConfig } from './router.config'
export class Router extends React.Component{
render(){
return(
<HashRouter>
<Switch>
<FrontendAuth config={routerConfig} />
</Switch>
</HashRouter>
);
}
}
所有的路由跳转,都交给 FrontendAuth 高阶组件代理完成。下面是 FrontendAuth 组件的实现:
import * as React from 'react';
import { Route,Redirect } from 'react-router-dom';
import { propsModel } from './frontend-auth.model'
export class FrontendAuth extends React.Component<any,propsModel>{
render(){
const { location,config } = this.props;
const { pathname } = location;
const isLogin = localStorage.getItem('__config_center_token')
// 如果该路由不用进行权限校验,登录状态下登陆页除外
// 因为登陆后,无法跳转到登陆页
// 这部分代码,是为了在非登陆状态下,访问不需要权限校验的路由
const targetRouterConfig = config.find((v:any) => v.path === pathname);
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='/404' />
}
}
}else{
// 非登陆状态下,当路由合法时且需要权限校验时,跳转到登陆页面,要求登陆
if(targetRouterConfig && targetRouterConfig.auth){
return <Redirect to='/login' />
}else{
// 非登陆状态下,路由不合法时,重定向至 404
return <Redirect to='/404' />
}
}
}
}
以及对应的 Model:
export interface propsModel {
config:any[],
}
页面上的路由跳转,都由 FrontendAuth 高阶组件代理了,在 Switch 组件内部,不再是 Route 组件,而只有一个 FrontendAuth 组件。
FrontendAuth 组件接收一个名为 config 的 Props,这是一份路由表。同时,由于 FrontendAuth 组件放在了 Switch 组件内部,React Router 还自动为 FrontendAuth 注入了 location 属性,当地址栏的路由发生变化时,就会触发 location 属性对象上的 pathname 属性发生变化,从而触发 FrontendAuth 的更新(调用 render 函数)。
FrontendAuth 的 render 函数中,根据 pathname 查找到路由表中的相关配置,如果该配置中指定了无需校验,就直接返回相应的 Route 组件。
如果查找到的配置需要进行校验,再根据是否登陆进行处理,具体可以查看代码中的注释。
总结一下,实现路由守卫需要考虑到以下的问题:
- 未登录情况下,访问不需要权限校验的合法页面:允许访问
- 登陆情况下,访问登陆页面:禁止访问,跳转至主页
- 登陆情况下,访问除登陆页以外的合法页面:允许访问
- 登陆情况下,访问所有的非法页面:禁止访问,跳转至 404
- 未登录情况下,访问需要权限校验的页面:禁止访问,跳转至登陆页
- 未登录情况下,访问所有的非法页面:禁止访问,跳转至 404
作者:黑黢黢
链接:https://www.jianshu.com/p/677433245697
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
React Router 4.0 实现路由守卫的更多相关文章
- React Router 4.0 ---- 嵌套路由和动态路由
嵌套路由,从广义上来说,分为两种情况:一种是每个路由到的组件都有共有的内容,这时把共有的内容抽离成一个组件,变化的内容也是一个组件,两种组件组合嵌套,形成一个新的组件.另一种是子路由,路由到的组件内部 ...
- react router @4 和 vue路由 详解(七)react路由守卫
完整版:https://www.cnblogs.com/yangyangxxb/p/10066650.html 12.react路由守卫? a.在之前的版本中,React Router 也提供了类似的 ...
- react router 4.0以上的路由应用
thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr& ...
- react router @4 和 vue路由 详解(全)
react router @4 和 vue路由 本文大纲: 1.vue路由基础和使用 2.react-router @4用法 3.什么是包容性路由?什么是排他性路由? 4.react路由有两个重要的属 ...
- 初步学习React Router 4.0
React Router 4.0 是react官方推荐的路由库.4是已经正式发布的最新版本. 初始化项目启动之后: npm run eject 弹出配置文件.自定义配置webpack 查看下pac ...
- React Router 4.0 + webpack 实现组件按需加载
网上关于React Router 4.0的按需加载文章有很多,大致的思路都一样,但是其实具体实现起来却要根据自己的实际情况来定,这里主要介绍一下我的实现方式. 主要方式是通过Route组件的rende ...
- React Router 4.0 体验
React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件.所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(声明式编 ...
- react router @4 和 vue路由 详解(八)vue路由守卫
完整版:https://www.cnblogs.com/yangyangxxb/p/10066650.html 13.vue路由守卫 a.beforeEach 全局守卫 (每个路由调用前都会触发,根据 ...
- React Router V4.0学习笔记
最近在学习React Router,但是网站的教程多半还是3.X版本之前的,所以我只能在GitHub上找到React Router的官方文档在读.后来总结了一下,包括学习经验以及V3.X与V4.X的差 ...
随机推荐
- AutoHotkey批量L版代码转H2的vim脚本
原脚本尽量用表达式的语法写,错误会比较少,比如"If a=", "fun(a=1)"这种语法在V2会出错文件放vim的autoload目录下,可使用以下map使 ...
- Stage划分和Task最佳位置算法源码彻底解密
本课主题 Job Stage 划分算法解密 Task 最佳位置算法实现解密 引言 作业调度的划分算法以及 Task 的最佳计算位置的算法,因为 Stage 的划分是DAGScheduler 工作的核心 ...
- vsphere的P2V工具做的物理机迁移到虚拟机报错out of memory
vsphere的P2V工具做的物理机迁移到虚拟机 迁移成功,但是启动报错 进入rescue模式后发现是sysctl.conf文件的参数设大了因为虚拟机的内存没有物理机内存大 kernel.shm ...
- 使用jMeter构造逻辑上有依赖关系的一系列并发请求
相信前端开发工程师对CSRF(Cross-site request forgery)跨站请求伪造这个概念都非常熟悉,有的时候也简写成XSRF,是一种对网站的恶意利用. 尽管听起来像跨站脚本(XSS), ...
- 在Kubernetes上运行SAP UI5应用(下): 一个例子体会Kubernetes内容器的高可用性和弹性伸缩
上一篇文章 在Kubernetes上运行SAP UI5应用(上),我介绍了如何在Docker里运行一个简单的SAP UI5应用,并且已经成功地将一个包含了这个UI5应用的docker镜像上传到Dock ...
- Linux 系统查看tomcat控制台命令
前提进入tomcat/logs文件夹下 查看全部命令是:tail -f catalina.out 如果想查看具体文件的日志进入该文件所在目录然后命令如下: tail -f filename
- 记录一个比较少用的容器C++ std::bitset
bitset存储二进制数位. bitset就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素一般只占1 bit,相当于一个char元素所占空间的八分之一. bitset中的每个 ...
- (五)多点触控之兼容ViewPager
在上一篇文章中,自定义的ZoomImageView已经实现了自由缩放,自由移动以及双击放大与缩小的功能.已经可以投入使用这个控件了.下面我们就在ViewPager中使用这个控件.如果你还没读过上一篇文 ...
- [转]C# 指针之美
将C#图像库的基础部分开源了(https://github.com/xiaotie/GebImage).这个库比较简单,且离成熟还有一段距离,但它是一种新的开发模式的探索:以指针和非托管内存为主的C ...
- 简单使用idea Spring Boot搭建项目
第一步:使用Spring Initializr创建 第二步:项目配置 第三步:选择项目需要的依赖 第五步: ok 创建完成,修改仓库 maven{ url 'http://maven.aliyun.c ...