react路由拦截(路由守卫)

Posted qianlingvip

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react路由拦截(路由守卫)相关的知识,希望对你有一定的参考价值。

前言: 最近在做项目时候,遇到了返回时候如果用户没有保存表单,需要拦截路由跳转,并给出提示信息是否要退出。相信做过vue项目的小伙伴都对vue的路由守卫并不陌生,react中如何实现呢?(本分享是针对react-router的v5版本)

一、使用Prompt组件来完成

闲话不多说直接上干货,react-router包里边给我们提供了一个组件,来帮助我们完成路由守卫。它有两个参数when和message。

参数名称类型作用
whenbooleantrue 弹窗
false顺利跳转
messagefunction或者字符串函数返回true就顺利跳转,false停止跳转
字符串就弹窗字符串并停止跳转。
when值message值路由是否跳转是否弹出默认框
false无论message是函数返回任何值还是message是字符串后边结果都一样
truemessage是字符串
truemessage是函数返回值true
truemessage是函数返回值是字符串
truemessage是函数返回false

由于默认弹窗非常不好看,所以,要借助antd或者meet-react来美化弹框。通过上边表格值可知,当when值是true并且message是函数返回值为false时候,才会拦截路由同时,不会弹出默认弹出框。话不多说,直接上实例代码:

import   Dialog  from '@alifd/meet-react';
import React,  useEffect, useState from 'react';
import  Prompt, useHistory  from 'react-router';

import style from './index.module.scss';

export default function TestPage() 
  const history = useHistory();
  const [notAllowJump, setNotAllowJump] = useState(true);

  /**
   * 路由拦截
   * @param * location string
   * @returns boolean
   */
  function handleRouter() 
    const list = field.getValue('list');
    const equal = xxxxx(); // 判断两次值是不是一样 
    if (equal) 
    // 两次值一样,用户没改动数据,直接放行
      return true;
    
    Dialog.show(
      centered: true,
      content: '是否保存当前修改数据',
      onOk() 
      	// 用户需要提交,提交后要放行,先将when置为false,再提交操作
        setNotAllowJump(false);
        xxxxxSubmit(); // 继续提交
      ,
      async onCancel() 
      	// 用户不提交,直接放弃修改返回上一页。将when置为false再返回,注意setNotAllowJump操作是异步的。
        await setNotAllowJump(false);
        history.goBack();
      ,
    );
    // 用户有修改,返回false拦截跳转,同时屏蔽掉默认弹出框
    return false;
  

  return (
    <div className=style['test-page']>
      <Prompt when=notAllowJump message=handleRouter />
      <footer>
        我是页面内容
      </footer>
    </div>
  );

二、使用history.block拦截

block返回值路由是否跳转是否弹出默认框
true
false
string

通过观察返回值不难发现当block返回值是false时候,能够拦截路由跳转,并且不会弹出默认提示框。

import  useHistory  from 'react-router';
import   Dialog  from '@alifd/meet-react';
import React,  useEffect, useState from 'react';

import style from './index.module.scss';

export default function TestPage() 
  const history = useHistory();
  
  useEffect(() => 
    history.block(() => 
      Dialog.show(
        centered: true,
        content: '是否保存当前修改数据',
        onOk() 
          history.block(() => true); // 放开拦截提交操作,成功后在提交函数内跳出去
          xxxxxSubmit();
        ,
        async onCancel() 
          history.block(() => true);
          history.goBack();
        ,
      );
      // 开启路由拦截同时阻止默认弹出框
      return false;
    );
  , [history]);

  return (
    <div className=style['test-page']>
      <footer>
        我是页面内容
      </footer>
    </div>
  );


Vue/React实现路由鉴权/导航守卫/路由拦截(react-router v6)

欢迎来到我的博客
📔博主是一名大学在读本科生,主要学习方向是前端。
🍭目前已经更新了【Vue】、【React–从基础到实战】、【TypeScript】等等系列专栏
🛠目前正在学习的是🔥 R e a c t 框架 React框架 React框架🔥,中间穿插了一些基础知识的回顾
🌈博客主页👉codeMak1r.小新的博客

😇本文目录😇

本文被专栏【React–从基础到实战】收录

🕹坚持创作✏️,一起学习📖,码出未来👨🏻‍💻!

路由导航守卫

本节目标: 能够实现未登录时访问拦截并跳转到登录页面(路由鉴权实现)

1. React项目中

实现思路

自己封装 AuthRoute 路由鉴权高阶组件,实现未登录拦截,并跳转到登录页面

思路为:判断本地是否有token,如果有,就返回子组件,否则就重定向到登录Login

实现步骤

  1. 在 components 目录中,创建 AuthRoute/index.js 文件
  2. 判断是否登录
  3. 登录时,直接渲染相应页面组件
  4. 未登录时,重定向到登录页面
  5. 将需要鉴权的页面路由配置,替换为 AuthRoute 组件渲染

代码实现

components/AuthRoute/index.js

// 路由鉴权
// 1. 判断token是否存在
// 2. 如果存在 直接正常渲染
// 3. 如果不存在 重定向到登录路由

import  Navigate  from "react-router-dom";
import  getToken  from "@/utils";
// 高阶组件:把一个组件当成另外一个组件的参数传入 然后通过一定的判断 返回新的组件
// 这里的AuthRoute就是一个高阶组件

function AuthRoute( children ) 
  // 获取token
  const tokenStr = getToken()
  // 如果token存在 直接正常渲染
  if (tokenStr) 
    return <>children</>
  
  // 如果token不存在,重定向到登录路由
  else 
    return <Navigate to='/login' replace />
  

/*
 <AuthRoute> <Layout /> </AuthRoute> 
 登录:<> <Layout /> </>
 非登录:<Navigate to="/login" replace />
*/ 
export  AuthRoute 

注:utils工具函数getToken如下

// 从localstorage中取token
const getToken = () => 
return window.localStorage.getItem(key)

src/routes/index.js路由表文件

import Layout from "@/pages/Layout";
import Login from "@/pages/Login";
import  AuthRoute  from "@/components/AuthRoute";

// eslint-disable-next-line
export default [
  // 不需要鉴权的组件Login
  
    path: "/login",
    element: <Login />
  ,
  // 需要鉴权的组件Layout
  
    path: "/",
    element: <AuthRoute>
      <Layout />
    </AuthRoute>
  
]

2. Vue项目中

实现思路

在Vue的router路由表文件中,存在官方封装好的API:beforeEach

代码实现

/src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
// 路由懒加载
const Login = () => import(/* webpackChunkName: "login_home_welcome" */ '../components/Login.vue')
const Home = () => import(/* webpackChunkName: "login_home_welcome" */ '../components/Home.vue')
const Welcome = () => import(/* webpackChunkName: "login_home_welcome" */ '../components/Welcome.vue')
Vue.use(VueRouter)
const routes = [
  
    path: '/login',
    component: Login
  ,
  
    path: '/',
    redirect: '/login'
  ,
  
    path: '/home',
    component: Home,
    redirect: '/welcome',
    children: [
       path: "/welcome", component: Welcome 
    ]
  
]
const router = new VueRouter(
  routes
)
// 挂载路由导航守卫
router.beforeEach((to, from, next) => 
  // to代表将要访问的路径
  // from代表从哪个路径跳转而来
  // next是一个函数,表示放行
  //    next() 放行   next('/login') 强制跳转到login页面
  if (to.path === '/login') return next()
  // 获取token
  const tokenStr = window.sessionStorage.getItem('token')
  if (!tokenStr) return next('/login')
  next()
)

export default router

代码解释:
router.beforeEach用来设置Vue的路由导航守卫(路由拦截),其接收一个回调函数作为参数。
在回调函数内部,接收三个参数,顺序分别是:to , from , next
to代表将要访问的路径
from代表从哪个路径跳转而来
next是一个函数,表示放行
next() => 放行next('/login') => 强制跳转到login页面

以上是关于react路由拦截(路由守卫)的主要内容,如果未能解决你的问题,请参考以下文章

Vue,路由拦截,弹窗提示

Vue路由守卫详解

路由拦截方式 全局守卫导航

路由守卫和拦截器

vue-router 方法总结

Vue路由重定向、别名与导航守卫