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

news2025/2/12 7:48:39

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.将加载的对象放到localRoutes
  for (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: string
  userInfo: any
  userMenus: 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.id
      this.token = loginResult.data.token
      localCache.setCache(LOGIN_TOKEN, this.token)

      // 2.获取登录用户的详细信息(role信息)
      const userInfoResult = await getUserInfoById(id)
      const userInfo = userInfoResult.data
      this.userInfo = userInfo

      // 3.根据角色请求用户的权限(菜单menus)
      const userMenusResult = await getUserMenusByRoleId(this.userInfo.role.id)
      const userMenus = userMenusResult.data
      this.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 = token
        this.userInfo = userInfo
        this.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的pinia
  app.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'
  }

  // 如果是进入到main
  if (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
      }
    }
  }
}

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

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

相关文章

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;人脸识…

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

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

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

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

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

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

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

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

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

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

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

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

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

引言 在技术面试中&#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…

【深度学习入门实战】基于Keras的手写数字识别实战(附完整可视化分析)

​ 本人主页:机器学习司猫白 ok,话不多说,我们进入正题吧 项目概述 本案例使用经典的MNIST手写数字数据集,通过Keras构建全连接神经网络,实现0-9数字的分类识别。文章将包含: 关键概念图解完整实现代码训练过程可视化模型效果深度分析环境准备 import numpy as np impo…

SkyWalking 10.1.0 实战:从零构建全链路监控,解锁微服务性能优化新境界

文章目录 前言一、集成SkyWalking二、SkyWalking使用三、SkyWalking性能剖析四、SkyWalking 告警推送4.1 配置告警规则4.2 配置告警通知地址4.3 下发告警信息4.4 测试告警4.5 慢SQL查询 总结 前言 在传统监控系统中&#xff0c;我们通过进程监控和日志分析来发现系统问题&…

【通俗易懂说模型】反向传播(附多元分类与Softmax函数)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …

128,【1】buuctf [极客大挑战 2019]PHP

进入靶场 提示了备份文件 抓包&#xff0c;扫描 扫描出了两个有反应的 访问index.php没反应&#xff0c;但www.zip成功下载了文件 index.php里得到如下有用信息 <?phpinclude class.php;$select $_GET[select];$resunserialize($select);?> 所以我们要通过GET 方…

系统思考—双环学习

前几天&#xff0c;一个企业高管向我提到&#xff1a;“我们调整了N次方案&#xff0c;市场策略、团队激励、管理制度&#xff0c;能改的全改了&#xff0c;怎么还是不见起色&#xff1f;” 这让我想到典型的单环学习&#xff0c;简单来说就是&#xff1a;发现问题 → 采取行动…

QTreeView和QTableView单元格添加超链接

QTreeView和QTableView单元格添加超链接的方法类似,本文仅以QTreeView为例。 在QTableView仿Excel表头排序和筛选中已经实现了超链接的添加,但是需要借助delegate,这里介绍一种更简单的方式,无需借助delegate。 一.效果 二.实现 QHTreeView.h #ifndef QHTREEVIEW_H #def…