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

16vue3实战-----动态路由

16vue3实战-----动态路由

  • 1.思路
  • 2.实现
    • 2.1创建所有的vue组件
    • 2.2创建所有的路由对象文件(与上述中的vue文件一一对应)
    • 2.3动态加载所有的路由对象文件
    • 2.4根据菜单动态映射正确的路由
    • 2.5解决main页面刷新的问题
    • 2.6解决main的第一个页面匹配显示的问题
    • 2.7根据path匹配menu

1.思路

思路可以看我写的另外一篇文章https://blog.csdn.net/fageaaa/article/details/145559821中的4.2(2)。那篇文章是以vue2为例,但思路差不多,只不过vue2和vue3中一些代码的书写有所不同。

2.实现

2.1创建所有的vue组件

在这里插入图片描述

2.2创建所有的路由对象文件(与上述中的vue文件一一对应)

在这里插入图片描述
路由对象文件内部内容,以main/user/user.ts为例:

export default {path: '/main/system/user',component: () => import('@/views/main/system/user/user.vue')
}

2.3动态加载所有的路由对象文件

可能有些公司没有把每个路由信息分别保存在各个文件,而是直接在一个文件中直接聚集,这样子当然也不会有问题。这里我是让每个ts文件就保存自己的路由信息,直接自动化读取。
把这个功能提取到utils工具文件夹中,新建map-menus.ts:
在这里插入图片描述
utils/map-menus.ts:

import type { RouteRecordRaw } from 'vue-router'
function loadLocalRoutes() {// 1.动态获取所有的路由对象, 放到数组中// * 路由对象都在独立的文件中// * 从文件中将所有路由对象先读取数组中//RouteRecordRaw[]这种类型根据提示可以知道const localRoutes: RouteRecordRaw[] = []// 1.1.读取router/main所有的ts文件const files: Record<string, any> = import.meta.glob('../router/main/**/*.ts',{eager: true})// 1.2.将加载的对象放到localRoutesfor (const key in files) {const module = files[key]localRoutes.push(module.default)}return localRoutes
}

2.4根据菜单动态映射正确的路由

utils/map-menus.ts:

 export function mapMenusToRoutes(userMenus: any[]) {// 1.加载本地路由const localRoutes = loadLocalRoutes()// 2.根据菜单去匹配正确的路由const routes: RouteRecordRaw[] = []//这里是只用两层,如果是很多层,就需要用递归。代码稍微复杂一些,这里就不写。主要将动态添加路由的思路for (const menu of userMenus) {for (const submenu of menu.children) {const route = localRoutes.find((item) => item.path === submenu.url)if (route) {routes.push(route)}}}return routes
}

store/login/login.ts:

import { defineStore } from 'pinia'
import {accountLoginRequest,getUserInfoById,getUserMenusByRoleId
} from '@/service/login/login'
import type { IAccount } from '@/types'
import { localCache } from '@/utils/cache'
import { mapMenusToRoutes } from '@/utils/map-menus'
import router from '@/router'
import { LOGIN_TOKEN } from '@/global/constants'interface ILoginState {token: stringuserInfo: anyuserMenus: any
}const useLoginStore = defineStore('login', {// 如何制定state的类型state: (): ILoginState => ({token: '',userInfo: {},userMenus: []}),actions: {async loginAccountAction(account: IAccount) {// 1.账号登录, 获取token等信息const loginResult = await accountLoginRequest(account)const id = loginResult.data.idthis.token = loginResult.data.tokenlocalCache.setCache(LOGIN_TOKEN, this.token)// 2.获取登录用户的详细信息(role信息)const userInfoResult = await getUserInfoById(id)const userInfo = userInfoResult.datathis.userInfo = userInfo// 3.根据角色请求用户的权限(菜单menus)const userMenusResult = await getUserMenusByRoleId(this.userInfo.role.id)const userMenus = userMenusResult.datathis.userMenus = userMenus// 4.进行本地缓存localCache.setCache('userInfo', userInfo)localCache.setCache('userMenus', userMenus)// 重要: 动态的添加路由const routes = mapMenusToRoutes(userMenus)routes.forEach((route) => router.addRoute('main', route))// 5.页面跳转(main页面)router.push('/main')},}
})export default useLoginStore

2.5解决main页面刷新的问题

问题:如果我们重新刷新的话动态路由就会消失,动态路由是在登录成功之后才会调用,刷新的时候并没有调用,所以动态路由没有添加上。
思路:在页面进行刷新的时候,需要初始化动态路由。
初始化动态路由代码如下,store/login/login.ts:

...
const useLoginStore = defineStore('login', {// 如何制定state的类型state: (): ILoginState => ({token: '',userInfo: {},userMenus: []}),actions: {async loginAccountAction(account: IAccount) {...// 重要: 动态的添加路由const routes = mapMenusToRoutes(userMenus)routes.forEach((route) => router.addRoute('main', route))// 5.页面跳转(main页面)router.push('/main')},//初始化动态路由loadLocalCacheAction() {// 1.用户进行刷新默认加载数据const token = localCache.getCache(LOGIN_TOKEN)const userInfo = localCache.getCache('userInfo')const userMenus = localCache.getCache('userMenus')if (token && userInfo && userMenus) {this.token = tokenthis.userInfo = userInfothis.userMenus = userMenus// 2.动态添加路由const routes = mapMenusToRoutes(userMenus)routes.forEach((route) => router.addRoute('main', route))}}}
})
export default useLoginStore

store/index.ts:

import { createPinia } from 'pinia'
import type { App } from 'vue'
import useLoginStore from './login/login'const pinia = createPinia()
function registerStore(app: App<Element>) {// 1.use的piniaapp.use(pinia)// 2.加载本地的数据const loginStore = useLoginStore()//初始化动态路由loginStore.loadLocalCacheAction()
}
export default registerStore

src/main.ts:

import { createApp } from 'vue'
import 'normalize.css'
import './assets/css/index.less'
import App from './App.vue'
import router from './router'
import store from './store'
import icons from './global/register-icons'const app = createApp(App)
app.use(icons)
app.use(store)
app.use(router)
app.mount('#app')

这样子在页面刷新时候就可以执行“初始化动态路由”的方法了。

2.6解决main的第一个页面匹配显示的问题

改进一下mapMenusToRoutes:

export let firstMenu: any = null
export function mapMenusToRoutes(userMenus: any[]) {// 1.加载本地路由const localRoutes = loadLocalRoutes()// 2.根据菜单去匹配正确的路由const routes: RouteRecordRaw[] = []for (const menu of userMenus) {for (const submenu of menu.children) {const route = localRoutes.find((item) => item.path === submenu.url)if (route) {// 1.给route的顶层菜单增加重定向功能(但是只需要添加一次即可)if (!routes.find((item) => item.path === menu.url)) {routes.push({ path: menu.url, redirect: route.path })}// 2.将二级菜单对应的路径routes.push(route)}// 记录第一个被匹配到的菜单if (!firstMenu && route) firstMenu = submenu}}return routes
}

在router/index.ts中:

router.beforeEach((to) => {// 只有登录成功(token), 才能真正进入到main页面const token = localCache.getCache(LOGIN_TOKEN)if (to.path.startsWith('/main') && !token) {return '/login'}// 如果是进入到mainif (to.path === '/main') {return firstMenu?.url}
})

2.7根据path匹配menu

utils/map-menus.ts:

/*** 根据路径去匹配需要显示的菜单* @param path 需要匹配的路径* @param userMenus 所有的菜单*/
export function mapPathToMenu(path: string, userMenus: any[]) {for (const menu of userMenus) {for (const submenu of menu.children) {if (submenu.url === path) {return submenu}}}
}

相关文章:

16vue3实战-----动态路由

16vue3实战-----动态路由 1.思路2.实现2.1创建所有的vue组件2.2创建所有的路由对象文件(与上述中的vue文件一一对应)2.3动态加载所有的路由对象文件2.4根据菜单动态映射正确的路由2.5解决main页面刷新的问题2.6解决main的第一个页面匹配显示的问题2.7根据path匹配menu 1.思路 …...

Linux常见命令——系统定时任务

文章目录 crontab 服务管理crontab -e :编辑crontab 定时任务crontab -l 查看crontab 任务crontab -r 删除当前用户所有的crontab 任务 crontab 服务管理 systemctl status crond该系统进程是开机自启动&#xff0c;并且被打开了&#xff0c;可以使用。 crontab -e :编辑cr…...

ARM Cortex-M3/M4 权威指南 笔记【一】技术综述

一、Cortex-M3/M4 处理器的一般信息 1.1 处理器类型 ARM Cortex-M 为 32 位 RISC&#xff08;精简指令集&#xff09;处理器&#xff0c;其具有&#xff1a; 32位寄存器32位内部数据通路32位总线接口 除了 32 位数据&#xff0c;Cortex-M 处理器&#xff08;以及其他任何 A…...

常用的AI算法介绍

常用的AI算法介绍 自然语言生成&#xff08;NLG&#xff09;&#xff1a;让机器写作&#xff0c;写诗 语言识别&#xff1a;语音模型的识别 虚拟现实&#xff1a;VR、增强现实&#xff08;AR&#xff09; 机器学习平台&#xff1a;针对AI优化的硬件和芯片&#xff08;人脸识…...

Spring常用注解和组件

引言 了解Spring常用注解的使用方式可以帮助我们更快速理解这个框架和其中的深度 注解 Configuration&#xff1a;表示该类是一个配置类&#xff0c;用于定义 Spring Bean。 EnableAutoConfiguration&#xff1a;启用 Spring Boot 的自动配置功能&#xff0c;让 Spring Boo…...

android的ViewModel这个类就是业务逻辑层吗

android的ViewModel这个类就是业务逻辑层吗&#xff1f; 相似&#xff1a;业务逻辑代码应该放在ViewModel这个类吗&#xff1f; 嗯&#xff0c;我现在在学习Android架构组件&#xff0c;特别是ViewModel。用户问ViewModel是否就是业务逻辑层&#xff0c;我需要仔细思考这个问题…...

3、kubectl 命令详解

kubectl 命令详解 kubectl 简介kubectl 常用操作基本信息查看命名空间的增删改查操作查看 pod 信息 项目的生命周期创建发布更新回滚删除金丝雀发布&#xff08;Canary Release&#xff09; 声明式管理方法 kubectl 简介 kubernetes 集群管理集群资源的唯一入口是通过相应的方…...

Qt Pro、Pri、Prf

一、概述 1、在Qt中&#xff0c;通常使用.pro(project)、pri(private include)、prf(project file)三种文件扩展名来组织项目。对于模块化编程&#xff0c;Qt提供了Pro和Pri&#xff0c;Pro管理项目&#xff0c;Pri管理模块。 2、pro文件是Qt项目的核心文件&#xff0c;包含了…...

fps动作系统9:动画音频

文章目录 动画音频创建音频蓝图cue音量乘数 音效衰减衰减空间 绑定到动画动画序列轨道 动画音频 创建音频蓝图 cue 音量乘数 音量大小 音效衰减 空间音效 衰减 空间 绑定到动画 动画序列 轨道 横着的方向是有不同的轨道的&#xff0c;阴影的就是。...

1064 - You have an error in your SQL syntax;

在创建数据库表建立外键是遇到了如下报错 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near position(position_id) ) at line 8 数据库表sql如下&#xff1a; --职位表 CR…...

Java在大数据处理中的应用:从MapReduce到Spark

Java在大数据处理中的应用&#xff1a;从MapReduce到Spark 大数据时代的到来让数据的存储、处理和分析变得前所未有的重要。随着数据量的剧增&#xff0c;传统的单机计算方式已经无法满足处理需求。为了解决这个问题&#xff0c;许多分布式计算框架应运而生&#xff0c;其中Ma…...

SwiftUI 中 .overlay 两种写法的区别及拓展

SwiftUI 中 .overlay 两种写法的区别及拓展 一、.overlay 简介功能语法 二、写法 1&#xff1a;.overlay(Circle().stroke(Color.blue, lineWidth: 2))代码示例解释优点适用场景 三、写法 2&#xff1a;.overlay { Circle().stroke(.white, lineWidth: 4) }代码示例解释优点适用…...

深入理解QT的View-Model-Delegate机制和用法

文章目录 Model-View-Delegate机制Model(数据模型)设置模型属性访问元素操作元素数据排序封装好的模型View(视图)显示数据数据选择Delegate(代理)数据选择易用封装类QListWidgetQTreeWidgetQTableWidget元素拖拽代理模型参考示例Model-View-Delegate机制 Qt的View/Model/Deleg…...

C# ASP.NET 介绍

.NET学习资料 .NET学习资料 .NET学习资料 一、概述 ASP.NET是由微软创建的一个开源 Web 框架&#xff0c;用于使用.NET 构建现代化的 Web 应用程序和服务。它为开发者提供了一套丰富的工具、库和编程模型&#xff0c;使得创建功能强大、高效且安全的 Web 应用变得更加容易。…...

深入理解指针初阶:从概念到实践

一、引言 在 C 语言的学习旅程中&#xff0c;指针无疑是一座必须翻越的高峰。它强大而灵活&#xff0c;掌握指针&#xff0c;能让我们更高效地操作内存&#xff0c;编写出更优化的代码。但指针也常常让初学者望而生畏&#xff0c;觉得它复杂难懂。别担心&#xff0c;本文将用通…...

《手札·行业篇》开源Odoo MES系统与SKF Observer Phoenix API在化工行业的双向对接方案

一、项目背景 化工行业生产过程复杂&#xff0c;设备运行条件恶劣&#xff0c;对设备状态监测、生产数据采集和质量控制的要求极高。通过开源Odoo MES系统与SKF Observer Phoenix API的双向对接&#xff0c;可以实现设备状态的实时监测、生产数据的自动化采集以及质量数据的同步…...

oracle11g搭建主从集群

安装oracle11g参考&#xff1a;centos安装oracle11g数据库-CSDN博客 一、主库操作 sqlplus / as sysdba 1、开启归档模式和强制日志模式 shutdown immediate startup mount #开启归档模式和强制日志模式 alter database archivelog; alter database force logging; #开启补…...

暂未整理啊

测码学院 python的数据类型 不可变数据类型&#xff1a;字符串/数字/元组/ type&#xff08;变量名&#xff09; 获得数据的类型 str&#xff1a;字符串 int&#xff1a;整数 float&#xff1a;浮点数 bool&#xff1a;true/false 布尔类型 list&#xff1a;列表 dict&…...

重庆西站公路桥梁自动化监测

1.项目概述 重庆西站属于渝黔铁路的配套工程&#xff0c;是承担兰渝、川黔、渝昆等多条铁路的特级客运站&#xff0c;未来重庆铁路三大客运站之一。作为我国西部地区规模最大的火车站、重庆西站于2014年在沙坪坝区上桥开工建设,该站东临内环高速&#xff0c;西靠中梁山&#x…...

JavaScript系列(70)--响应式编程进阶详解

JavaScript响应式编程进阶详解 &#x1f504; 今天&#xff0c;让我们深入探讨JavaScript响应式编程的进阶内容。响应式编程是一种强大的编程范式&#xff0c;它能够帮助我们更好地处理异步数据流和状态管理。 响应式编程进阶概念 &#x1f31f; &#x1f4a1; 小知识&#x…...

安装指定版本的pnpm

要安装指定版本的 pnpm&#xff0c;可以使用以下方法&#xff1a; 方法 1: 使用 pnpm 安装指定版本 你可以通过 pnpm 的 add 命令来安装指定版本&#xff1a; pnpm add -g pnpm<版本号>例如&#xff0c;安装 pnpm 的 7.0.0 版本&#xff1a; pnpm add -g pnpm7.0.0方法…...

Dockerfiles 的 Top 10 常见 DevOps/SRE 面试问题及答案

1. RUN 和 CMD 之间有什么区别&#xff1f; RUN : 在镜像构建过程中执行命令&#xff0c;创建一个新的层。通常用于安装软件包。 示例: RUN apt-get update && apt-get install -y curlCMD : 指定容器启动时默认运行的命令。它在运行时执行&#xff0c;而不是在构建过程…...

头条百度批量采集软件说明文档

旧版说明文档《头条号文章批量采集软件4.0版本说明文档&#xff01;头条/微头条文章批量采集》 头条的采集软件已经更新了好多个版本了&#xff0c;一直没有做详细的介绍文档&#xff0c;最近更新了一些功能进去&#xff0c;一块来写一下说明文档。 1、主界面 2、头条作者采集…...

36.日常算法

1.最小栈 题目来源 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void pop() 删除堆栈顶部的元素。 int top() 获取堆…...

计算机考研复试上机04

目录 6、向量 1&#xff09;完数与盈数&#xff08;清华大学复试上机题&#xff09; 7、队列 1&#xff09;约瑟夫问题 No. 2 8、栈 1&#xff09;简单计算器&#xff08;浙江大学复试上机题&#xff09; 2&#xff09;堆栈的使用&#xff08;吉林大学复试上机题&#xf…...

【面试】面试常见的智力题

引言 在技术面试中&#xff0c;除了考察编程能力和算法知识外&#xff0c;智力题也是常见的考察方式。智力题不仅能够测试候选人的逻辑思维能力&#xff0c;还能反映其解决问题的创造力和应变能力。本文将整理一些常见的面试智力题&#xff0c;并详细分析解题思路&#xff0c;…...

【动态规划】风扫枯杨,满地堆黄叶 - 9. 完全背包问题

本篇博客给大家带来的是完全背包问题之动态规划解法技巧. &#x1f40e;文章专栏: 动态规划 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅&#x1f680; 要开心要快乐顺…...

BGP基础协议详解

BGP基础协议详解 一、BGP在企业中的应用二、BGP概述2.1 BGP的特点2.2 基本配置演示2.3 抓包观察2.4 BGP的特征三、BGP对等体关系四、bgp报文4.1 BGP五种报文类型(重点)4.2 BGP报文格式-报文头格式4.3 Open报文格式4.4 Update报文格式4.5 Notification报文格式4.6 Route-refre…...

LeetCode刷题---数组---840

矩阵中的幻方 https://leetcode.cn/problems/magic-squares-in-grid/submissions/598584907/ 题目&#xff1a; 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成…...

Visual Studio踩过的坑

统计Unity项目代码行数 编辑-查找和替换-在文件中查找 查找内容输入 b*[^:b#/].*$ 勾选“使用正则表达式” 文件类型留空 也有网友做了指定&#xff0c;供参考 !*\bin\*;!*\obj\*;!*\.*\*!*.meta;!*.prefab;!*.unity 打开Unity的项目 注意&#xff1a;只是看&#xff0…...