当前位置: 首页 > news >正文

react_14

动态路由

路由分成两部分:

  • 静态路由,固定的部分,如主页、404、login 这几个页面

  • 动态路由,变化的部分,经常是主页内的嵌套路由,比如 Student、Teacher 这些

动态路由应该是根据用户登录后,根据角色的不同,从后端服务获取,因为这些数据是变化的,所以用 mobx 来管理

在src\store\路径下新建RoutesStore.tsx

import axios from "axios";
import {LoginReq,LoginResp,Menu,MenuAndRoute,Route,
} from "../model/Student";
import R from "../model/R";
import { makeAutoObservable, runInAction } from "mobx";
import { Link, Navigate, RouteObject } from "react-router-dom";
import { load } from "../router/MyRouter";
import A8Main from "../pages/A8Main";
import A8NotFound from "../pages/A8NotFound";
import { ItemType } from "antd/es/menu/hooks/useItems";
import Icon from "./Icon";
//其中 convertMenu 为核心方法,负责将服务器返回的 Menu 转换成 antd Menu 组件需要的 Menu
function convertMenu(m: Menu): ItemType {const Label = m.routePath ? <Link to={m.routePath}>{m.label}</Link> : m.label;return {key: m.key,label: Label,icon: <Icon name={m.icon}></Icon>,children: m.children && m.children.map(convertMenu),};
}
class RoutesStore {dynamicRoutes: Route[] = [];dynamicMenus: Menu[] = [];token: string = "";message: string = "";state: string = "pending";async login(loginReq: LoginReq) {this.state = "pending";const resp1 = await axios.post<R<LoginResp>>("http://localhost:8080/api/loginJwt",loginReq);if (resp1.data.code === 999) {const resp2 = await axios.get<R<MenuAndRoute>>(`http://localhost:8080/api/menu/${loginReq.username}`);runInAction(() => {this.dynamicRoutes = resp2.data.data.routeList;localStorage.setItem("dynamicRoutes",JSON.stringify(this.dynamicRoutes));this.dynamicMenus = resp2.data.data.menuTree;localStorage.setItem("dynamicMenus", JSON.stringify(this.dynamicMenus));this.token = resp1.data.data.token;localStorage.setItem("token", this.token);this.state = "success";});} else {runInAction(() => {this.state = "error";this.message = resp1.data.message || "未知错误";});}}/*   async fetch(username: string) {const resp = await axios.get<R<MenuAndRoute>>(`http://localhost:8080/api/menu/${username}`);runInAction(() => {this.dynamicRoutes = resp.data.data.routeList;//当在浏览器地址栏重新输入路径的时候,会重新向7070服务器发送一个请求,导致RoutesStore.tsx重新执行,//导致路由对象重新被创建,那么登录之后获得的动态路由数据就会丢失,所以为了防止这种情况,把登录后获得的//路由数据存入到localStorage中localStorage.setItem("dynamicRoutes", JSON.stringify(this.dynamicRoutes));this.dynamicMenus = resp.data.data.menuTree;localStorage.setItem("dynamicMenus", JSON.stringify(this.dynamicMenus));});} */get routes() {const staticRoutes: RouteObject[] = [{path: "/login",element: load("A8Login"),},{path: "/",element: <A8Main></A8Main>,children: [],},{path: "/404",element: <A8NotFound></A8NotFound>,},// 使用这个路径,上面的路径匹配不到时,显示notFound页面,但是路径还是输入的路径不变{ path: "/*", element: <A8NotFound></A8NotFound> },//   使用这种路径写法的时候,上面的路径匹配不到时,页面是重定向到notFound,路径会跳转到404{path: "/*",element: <Navigate to={"/404"}></Navigate>,},];staticRoutes[1].children = this.dynamicRoutes.map((r) => {return { path: r.path, element: load(r.element) };});return staticRoutes;}get menus() {return this.dynamicMenus.map(convertMenu);}get username() {if (this.token.length === 0) {return "";}
//token 的前两部分都可以解码出来,其中 [1] 就是 token 的内容部分const json = atob(this.token.split(".")[1]);//parse方法把字符串还原成对象return JSON.parse(json).sub;}constructor() {makeAutoObservable(this);//页面刷新会重新调用构造器,这个时候从localStorage中获取存储的路由数据const routesJson = localStorage.getItem("dynamicRoutes");this.dynamicRoutes = routesJson ? JSON.parse(routesJson) : [];const menusJson = localStorage.getItem("dynamicMenus");this.dynamicMenus = menusJson ? JSON.parse(menusJson) : [];}reset() {localStorage.removeItem("dynamicRoutes");this.dynamicRoutes = [];localStorage.removeItem("dynamicMenus");this.dynamicMenus = [];localStorage.removeItem("token");this.token = "";this.state = "pending";}
}
export default new RoutesStore();
  • 其中用 localStorage 进行了数据的持久化,避免刷新后丢失数据

  • 跳转若发生错误,可能是因为组件懒加载引起的,需要用 Suspense 解决

  • root.render(<ConfigProvider locale={zhCN}><BrowserRouter><Suspense fallback={<h3>加载中...</h3>}><MyRouter></MyRouter></Suspense></BrowserRouter></ConfigProvider>
    )

相关文章:

  • 香港金融科技周2023:AIGC重塑金融形态
  • 性能指标>软硬件的性能指标
  • Linux中阶教程:bash shell基础
  • 提升之学习方法
  • 【Redis】String字符串类型-内部编码使用场景
  • Nginx搭载负载均衡及前端项目部署
  • Flink源码解析三之执行计划⽣成
  • 自定义SpringMVC拦截器,实现内外网访问控制功能
  • 2022年06月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • 0xGame Web 2023
  • druid开启日志,但关闭sql查询结果打印
  • Redis Part2
  • Linux yum 没有可用软件包 fping。 错误:无须任何处理 的解决办法
  • 【蓝桥杯省赛真题41】Scratch电脑开关机 蓝桥杯少儿编程scratch图形化编程 蓝桥杯省赛真题讲解
  • 解析电源模块功能测试项目 电源模块测试系统助力功能测试
  • cookie和session
  • FineReport中如何实现自动滚屏效果
  • vue 配置sass、scss全局变量
  • vue-cli3搭建项目
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 蓝海存储开关机注意事项总结
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 我建了一个叫Hello World的项目
  • 用mpvue开发微信小程序
  • 优化 Vue 项目编译文件大小
  • C# - 为值类型重定义相等性
  • PostgreSQL之连接数修改
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • ###C语言程序设计-----C语言学习(3)#
  • (42)STM32——LCD显示屏实验笔记
  • (7)STL算法之交换赋值
  • (C++17) std算法之执行策略 execution
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (南京观海微电子)——I3C协议介绍
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (十六)一篇文章学会Java的常用API
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • ***利用Ms05002溢出找“肉鸡
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET 动态调用WebService + WSE + UsernameToken
  • .NET 使用 XPath 来读写 XML 文件
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .Net8 Blazor 尝鲜
  • .NET单元测试
  • .NET框架设计—常被忽视的C#设计技巧
  • .net项目IIS、VS 附加进程调试
  • .py文件应该怎样打开?
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • @font-face 用字体画图标
  • [ C++ ] STL---string类的模拟实现
  • [20150629]简单的加密连接.txt