react-router-dom v6.5.0实现路由守卫RouterBeforeEach及缓存

news2024/11/25 16:31:05

一、概述

        最近留意下react-router-dom有更新到6.6.1的版本,在这个版本增加了不少的功能。研究了下,可以利用其提供的API实现一个类似Vue的路由守卫,从而简便达到路由鉴权的业务场景。这里我是使用npm的包,是react-router-dom v6.5.0,但是基本新增的功能都有。

Github:码源

react-router-dom官网

二、createHashRouter

        这个函数可以帮助我们,采用编程的方式生成一个路由。

import { createHashRouter,useRouteError,redirect} from "react-router-dom";
import { Suspense, lazy } from 'react'
import React from "react";
import KeepAlive from 'react-activation'

type IRouterBeforeLoad = (res:any, redirectUrl: string) => Boolean;
let routerLoader: IRouterBeforeLoad;
let _redirectUrl: string = "/";
const routes = [
  {
    path: '/',
    auth: false,
    name:"login",
    component:lazy(() => import('@/page/login/login'))
  },
  {
    path: '/Portal',
    name:"Portal",
    component:lazy(() => import('@/page/portal/portal')),
    children: [
      { 
        path: '/Portal/Home',
        name:"Home",
        component:lazy(() => import('@/page/home/home'))
      },
      { 
        path: '/Portal/Lifecycle',
        name:"Lifecycle",
        component:lazy(() => import('@/page/lifecycle/lifecycle'))
      },
      { 
        path: '/Portal/NotFound',
        name:"NotFound",
        component:lazy(() => import('@/page/error/NotFound'))
      },
      { 
        path: '*',
        component:lazy(() => import('../page/error/NotFound'))
      },
    ]
  },
  { 
    path: '*',
    component:lazy(() => import('../page/error/NotFound'))
  },
]


function ErrorBoundary() {
  let error:any = useRouteError();
  return <div>
    <div>{ error.message}</div>
    <div>{ error.stack}</div>
  </div>;
  return <></>
}

// 路由处理方式
const generateRouter = (routers:any) => {
  return routers.map((item:any) => {
    if (item.children) {
      item.children = generateRouter(item.children)
    }
    item.element = <Suspense fallback={
      <div>加载中...</div>
    }>
      {/* 把懒加载的异步路由变成组件装载进去 */}
      <KeepAlive id={item.name} cacheKey={item.name}>
        <item.component />
      </KeepAlive>
    </Suspense>
    item.errorElement = <ErrorBoundary></ErrorBoundary>
    item.loader = async (res: any) => {
      if (routerLoader && !item.children) {
        if (routerLoader(res,_redirectUrl)) {
          return res;
        } else { 
          return redirect(_redirectUrl);
        }
      }
      return res;
    }
    return item
  })
}

const RouterLoader = (fun: IRouterBeforeLoad) => {
  routerLoader = fun;
}

const Router  = ()=>createHashRouter(generateRouter([...routes]))
export{ Router,RouterLoader}

三、errorElement、useRouteError

        路由中errorElement属性是新加的,其接受一个组件,在当前路由组件有错误的时候显示。但是这个功能和缓存组件<KeepAlive>组件有冲突。也就是目前使用缓存后,这个错误组件无法正常使用。可以留意下react-activation作者后续有没有修正这个bug。

        useRouteError这个hook是新增的,用于获取组件的报错信息。这里两个功能结合使用可以使错误信息自定义展示在页面,避免组件出错后,整个系统页面白屏。

 四、redirect

        重定向钩子,是目前官方提供的唯一一个非hook控制路由的钩子,其可以再纯js函数中使用,重新向路由。

五、自定义跳转hook,实现路由守卫RouterBeforeEach

        官方提供的路由跳转是使用useNavigate hook的,这里我们要实现路由守卫,那么我需要在路由跳转前做逻辑的判断,所以我自定义了一个useUtilsNavigate hook用于跳转前的判断。只要是通过这个hook跳转的路由都可以响应到路由守卫。

import { NavigateFunction, Location, To, NavigateOptions } from "react-router-dom";
import { RouterLoader } from "@/routes/route";
type IrouterBeforeLoad = (to:Ito,location?: Location) => Boolean;

interface Ito {
  to: To, options?: NavigateOptions
 }

let routerBeforeLoad: IrouterBeforeLoad;
let flag: Boolean = true;

const RouterBeforeEach = (fun: IrouterBeforeLoad) => {
  ///页面刷新时,配合loader实现调用,并做拦截重定向,由flag判断是否是初次刷新页面,以免在useUtilsNavigate调用是触发多次路由校验
  RouterLoader((res: any,redirectUrl:string) => { 
    let result: Boolean=true;
    if (flag) { 
      let url = new URL(res.request.url)
      result = fun({ to: url.pathname })
      if (redirectUrl==url.pathname) { 
        result = true;
      }
    }
    return result;
  })
  routerBeforeLoad = fun;
}

///所有的js路由跳转通过此函数,由此做路由拦截
const useUtilsNavigate=(navigate:NavigateFunction,location:Location,to: To, options?: NavigateOptions)=>{
  if (routerBeforeLoad && routerBeforeLoad({ to, options }, location)) {
    //flag设置false标志已经不是第一次加载页面
    flag = false;
    navigate(to, options)
  } else {
    return;
  }
  //flag设置false标志已经不是第一次加载页面
  flag = false;
  navigate(to,options)
}

export { useUtilsNavigate, RouterBeforeEach };
export type { IrouterBeforeLoad,Ito };

RouterLoader这个函数钩子是在路由定义的文件里面导出的,可以看到在route.tsx,其在loader属性里面被调用。loader这个也是新版本提供的一个新功能,其会在组件页面加载时先回调这个钩子,我在这里根据flag判断是否页面初始加载。因为页面通过URL直接打开的话,是没有经过useUtilsNavigate,也就是无法通过它去做路由监听,所以需要使用loader这个钩子,在初次加载时,触发路由守卫。

六、在程序主入口注册路由守卫钩子

import ReactDOM from 'react-dom';
import {RouterProvider } from "react-router-dom";
import './index.css'
import { Router } from './routes/route';
import { AliveScope } from 'react-activation'
import React from 'react';
import { RouterBeforeEach } from "@/utils/useUtilsNavigate";
RouterBeforeEach(( to,from) => { 
  console.log("路由守卫to", to)
  console.log("路由守卫from", from)
  return true;
})

ReactDOM.render(
    <AliveScope>
      <RouterProvider router={Router()}/>
    </AliveScope>,
  document.getElementById('root')
);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/116209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode 124. 二叉树中的最大路径和-java题解

题目所属分类 二叉树的最大值 dfs 原题链接 路径 被定义为一条从树中任意节点出发&#xff0c;沿父节点-子节点连接&#xff0c;达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中…

Web Services 基于Apache Axis2 生成客户端代码示例

webservice 一种古老的技术&#xff0c;现在基本上已经弃用&#xff0c;但也有许多古董项目在用&#xff0c;整理并记录下自己的使用过程&#xff0c;避免更多的人踩坑。 Web Services 生成客户端代码步骤1 Apache Axis2下载安装1.1 认识Apache Axis21.2 下载Apache Axis22 通过…

当地的新员工入职培训

香港 (Xinwengao.com) — 在中国生活和工作的所有外国人都面临文化冲击。在他们的入职前期&#xff0c;学校管理层通常会让他们接受广泛的入职培训。这些培训项目旨在为外籍教师提供文化和专业培训。在外籍教师开始他们的教学之旅之前&#xff0c;向他们灌输文化同理心的美德非…

天气后报网爬虫及数据分析(python)

从天气后报网&#xff08;http://www.tianqihoubao.com&#xff09;中爬取绵阳市某一年的历史天气信息&#xff0c;包括每天最高气温、最低气温、天气状况、风向等&#xff0c;完成以下功能&#xff1a; &#xff08;1&#xff09;将获取的数据信息存储到“data.csv”文件中&a…

微服务(三)——远程调用

目录前言1. RestTemplate1. 导入依赖2. 代码3. 常用方法2. jodd-http1. 引入依赖2. 代码3. 测试3. Feign1. 引入依赖2. 使用过程3. 自定义配置4. 优化前言 微服务都是独立部署的&#xff0c;要实现一个业务可能需要多个服务之间的通信&#xff0c;所以远程调用必不可少&#x…

html标签分类及其他知识

1、标签按照类型可以划分为三种类型&#xff1a; block&#xff1a;div、p、ul、li、h1… 1、独占一行2、支持所有样式3、不写宽的时候&#xff0c;跟父元素的宽相同4、所占区域是一个矩形 inline&#xff1a;span、a、em、strong、img… 1、挨在一起2、有些样式不支持&#x…

编译原理——求后缀表达式、三元式、四元式

一、求后缀表达式 可能就是一填空题&#xff0c;考试应该也不会太复杂&#xff0c;要会&#xff0c;掌握着由外到内求解思想即可&#xff1b; 其实就是二叉树的后序遍历&#xff0c;左右根&#xff1b;拆分的顺序就是由左到右顺序进行&#xff0c;小括号内的最后拆&#xff0…

4线触摸屏控制器ET2046介绍

4线触摸屏控制器ET2046简介 ET2046是4线触摸屏控制器&#xff0c;支持1.5V&#xff5e;5.5V的低压I/O 接口。ET2046具有内置2.5V电压源&#xff0c;可用于辅助输入、电池监测和温度检测模式的测量。在不使用时&#xff0c;也可将内置电压源关闭以节约电力。内置电压源最低可工作…

JS 执行机制

1、JS 是单线程 JavaScript 语言的一大特点就是单线程&#xff0c;也就是说&#xff0c;同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互&#xff0c;以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加…

建议使用这些方法来优化Mac,运行速度直线上升

Mac系统的稳定性和流畅性一直备受大家称赞&#xff0c;这也是大多数人选择Mac的原因&#xff0c;尽管如此&#xff0c;我们仍不时地对Mac进行优化、调整&#xff0c;以使其比以前更快、更流畅地运行。以下是小编分享给各位的Mac优化方法&#xff0c;记得保存哦~ 一、释放被过度…

Groovy安全高效的执行(死循环,休眠,危险方法)

背景 在很多场景下有需要执行异步任务&#xff0c;或者执行用户的自定义任务时&#xff0c;通常我们会使用Groovy脚本能力来完成任务。通过groovy动态脚本能力&#xff0c;在业务执行过程中动态执行不同业务线或者用户的脚本&#xff0c;来满足不同需求。 这样可以非常方便的进…

关于CSS选择器优先级的规则说明

简单规则&#xff1a; !important > 行内样式 > id选择器 > 类选择器 > 元素选择器 > 通配选择器 选择器举例说明&#xff1a; !important&#xff1a; <h1 id"title">好好学习&#xff0c;天天向上</h1> <style type"text/…

ArcGIS基础实验操作100例--实验1绘制自定义线、垂线、平行线

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a; 通过百度网盘分享的文件&#xff1a;地理信息系统基础实验100例 链接:https://pan.baidu.com/s/1sprJ2eyDAkYWiLwyuTIf1g 提取码:gb7y 复制这段内容…

Doris(一)

1、Doris简介 Doris是由百度大数据研发&#xff0c;是一个现代化的MPP&#xff08;Massively Parallel Processing&#xff09;大规模并行处理的分析型数据库产品。仅需亚秒级响应时间即可获得查询结果&#xff0c;有效地支持实时数据分析。 Apache Doris 的分布式架构非常简洁…

北上广深杭房价高压下,这也许是软件测试员扎根的唯一出路...

简单算一笔账&#xff0c;目前小公司软件测试员工资一般是1万出头&#xff0c;年薪普遍在20万以下。在不考虑通胀和工资增长的情况下&#xff0c;除去吃喝需要攒30年才能攒出一线城市房子的首付&#xff0c;以这样的收入水平&#xff0c;基本上没法扎根。 想拿高薪最好的途径就…

API文档、技术文档工具 - ShowDoc - 使用

1.应用场景 主要用于使用适合IT团队的 API文档、技术文档工具 进行项目文档书写以及进行开发。 2.学习/操作 1.文档阅读 ShowDoc ShowDoc - demo 安装/升级手册 GitHub - star7th/showdoc: ShowDoc is a tool greatly applicable for an IT team to share documents online一…

LeetCode Hot 100~Day3

目录 字母异位词分组 最大子数组和 跳跃游戏 合并区间 不同路径 最小路径和 爬楼梯 颜色分类 子集 单词搜索 二叉树的中序遍历 不同的二叉搜索树 字母异位词分组 题目链接&#xff1a;49. 字母异位词分组 示例 输入: strs ["eat", "tea&quo…

[DonkeyCar][树莓派]基础01 - 首次配置 - WIFI

2022年圣诞节到来啦&#xff0c;疫情把刚刚起来的工作似乎又慢了下来&#xff0c;在冲刺决赛圈的同时&#xff0c;也许开一个新的领域&#xff0c;写一个博客是比较好的方式。 一、前言 拿到树莓派开发板的时候&#xff0c;一般&#xff0c;供应商都会配合烧录的镜像。但是&am…

《图解TCP/IP》阅读笔记(第七章 7.6)—— BGP 边界网关协议

7.6 BGP BGP&#xff08;Border Gateway Protocol&#xff09;&#xff0c;边界网关协议&#xff0c;是用于连接不同组织机构&#xff08;或者说不同自治系统&#xff09;的一种协议&#xff0c;其属于EGP&#xff08;外部网关协议&#xff09;&#xff0c;我们在7.2节中了解过…

01)FastDFS文件服务器安装和测试可用性

FastDFS简介 ​ FastDFS是一个轻量级的开源分布式文件系统。2008年4月份开始启动。类似google FS的一个轻量级分布式文件系统,纯C实现,支持Linux、FreeBSD、AIX等UNIX系统。 ​ 主要解决了大容量的文件存储和高并发访问的问题,文件存取时实现了负载均衡。实现了软件方式的…