【Vue3-Element-Admin 动态路由】涉及到的配置

Vue3-Element-Admin 动态路由 涉及到的配置

  • 0. Vue3-Element-Admin 项目地址
  • 1. router/index.ts
  • 2. Mock接口模拟数据
  • 3. store/permission
  • 4. api/menu
  • 5. plugins/permission

这篇文章讲的主要是 Vue3-Element-Admin 差不多内置的动态路由配置 (根据后端接口渲染)

先把开发环境(.env.development)中的 VITE_MOCK_DEV_SERVER 设置为 true 这代表启用 Mock 服务
Mock 数据模拟 在 vite 中已经配置好了
在这里插入图片描述

0. Vue3-Element-Admin 项目地址

Vue3-Element-Admin:Vue3-Element-Admin

1. router/index.ts

这个文件主要放一些静态初始路由,可以不用管

import type { App } from 'vue'
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'export const Layout = () => import('@/layout/index.vue')// 静态路由
export const constantRoutes: RouteRecordRaw[] = [{path: '/redirect',component: Layout,meta: { hidden: true },children: [{path: '/redirect/:path(.*)',component: () => import('@/views/redirect/index.vue')}]},{path: '/login',component: () => import('@/views/login/index.vue'),meta: { hidden: true }},{path: '/',name: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',component: () => import('@/views/dashboard/index.vue'),name: 'Dashboard', // 用于 keep-alive, 必须与SFC自动推导或者显示声明的组件name一致// https://cn.vuejs.org/guide/built-ins/keep-alive.html#include-excludemeta: {title: 'dashboard',icon: 'homepage',affix: true,keepAlive: true,alwaysShow: false}},{path: '401',component: () => import('@/views/error-page/401.vue'),meta: { hidden: true }},{path: '404',component: () => import('@/views/error-page/404.vue'),meta: { hidden: true }}]}
]/*** 创建路由*/
const router = createRouter({history: createWebHistory(),routes: constantRoutes,// 刷新时,滚动条位置还原scrollBehavior: () => ({ left: 0, top: 0 })
})// 全局注册 router
export function setupRouter(app: App<Element>) {app.use(router)
}/*** 重置路由*/
export function resetRouter() {router.replace({ path: '/login' })
}export default router

2. Mock接口模拟数据

如果目前没有后端接口支持的话,可以先去文件根目录 mock 文件夹中的 menu.mock.ts 查看,一开始可能会有很多数据,全改成我的就好,可以先模拟看一下

import { defineMock } from './base'export default defineMock([{url: 'menus/routes',method: ['GET'],body: {code: '00000',data: [{path: '/dashboard',component: 'Dashboard',redirect: '/dashboard',name: '/dashboard',meta: {title: '首页',icon: 'dashboard',hidden: true,roles: ['ADMIN'],alwaysShow: false,params: null}},{path: '/nihao',component: 'Layout',redirect: '/nihao/hello',name: '/nihao',meta: {title: '你好',icon: 'system',hidden: false,roles: ['ADMIN'],alwaysShow: true,params: null},children: [{path: 'hello',component: 'nihao/hello/index',name: 'Hello',meta: {title: 'Hello',icon: 'user',hidden: false,roles: ['ADMIN'],keepAlive: true,alwaysShow: false,params: null}}]},{path: '/system',component: 'Layout',redirect: '/system/user',name: '/system',meta: {title: '系统管理',icon: 'system',hidden: false,roles: ['ADMIN'],alwaysShow: true,params: null},children: [{path: 'user',component: 'system/user/index',name: 'User',meta: {title: 'Test1',icon: 'user',hidden: false,roles: ['ADMIN'],keepAlive: true,alwaysShow: false,params: null}},{path: 'user',component: 'system/user/index',name: 'User',meta: {title: 'Test2',icon: 'user',hidden: false,roles: ['ADMIN'],keepAlive: true,alwaysShow: false,params: null}}]}],msg: '一切ok'}}// ... 其他接口
])

3. store/permission

查看权限配置相关页面,这边主要是做一些角色鉴权、角色菜单权限,差不多都是菜单相关配置,主要看一下 generateRoutes 方法,它是配置动态路由所需要用到的方法,这边我是使用了我上面那个 Mock 接口,你可以看到
MenuAPI.getRoutes() .then(data => { //... })

import { RouteRecordRaw } from 'vue-router'
import { constantRoutes } from '@/router'
import { store } from '@/store'
import MenuAPI from '@/api/menu'
import { RouteVO } from '@/api/menu/model'const modules = import.meta.glob('../../views/**/**.vue')
const Layout = () => import('@/layout/index.vue')/*** Use meta.role to determine if the current user has permission** @param roles 用户角色集合* @param route 路由* @returns*/
const hasPermission = (roles: string[], route: RouteRecordRaw) => {if (route.meta && route.meta.roles) {// 角色【超级管理员】拥有所有权限,忽略校验if (roles.includes('ROOT')) {return true}return roles.some(role => {if (route.meta?.roles) {return route.meta.roles.includes(role)}})}return false
}/*** 递归过滤有权限的动态路由** @param routes 接口返回所有的动态路由* @param roles 用户角色集合* @returns 返回用户有权限的动态路由*/
const filterAsyncRoutes = (routes: RouteVO[], roles: string[]) => {const asyncRoutes: RouteRecordRaw[] = []routes.forEach(route => {const tmpRoute = { ...route } as RouteRecordRaw // 深拷贝 route 对象 避免污染if (hasPermission(roles, tmpRoute)) {// 如果是顶级目录,替换为 Layout 组件if (tmpRoute.component?.toString() == 'Layout') {tmpRoute.component = Layout} else {// 如果是子目录,动态加载组件const component = modules[`../../views/${tmpRoute.component}.vue`]if (component) {tmpRoute.component = component} else {tmpRoute.component = modules[`../../views/error-page/404.vue`]}}if (tmpRoute.children) {tmpRoute.children = filterAsyncRoutes(route.children, roles)}asyncRoutes.push(tmpRoute)}})return asyncRoutes
}
// setup
export const usePermissionStore = defineStore('permission', () => {// stateconst routes = ref<RouteRecordRaw[]>([])// actionsfunction setRoutes(newRoutes: RouteRecordRaw[]) {routes.value = constantRoutes.concat(newRoutes)}/*** 生成动态路由** @param roles 用户角色集合* @returns*/function generateRoutes(roles: string[]) {return new Promise<RouteRecordRaw[]>((resolve, reject) => {// 接口获取所有路由MenuAPI.getRoutes().then(data => {// 过滤有权限的动态路由const accessedRoutes = filterAsyncRoutes(data, roles)setRoutes(accessedRoutes)resolve(accessedRoutes)}).catch(error => {reject(error)})})}/*** 获取与激活的顶部菜单项相关的混合模式左侧菜单集合*/const mixLeftMenus = ref<RouteRecordRaw[]>([])function setMixLeftMenus(topMenuPath: string) {const matchedItem = routes.value.find(item => item.path === topMenuPath)if (matchedItem && matchedItem.children) {mixLeftMenus.value = matchedItem.children}}return {routes,setRoutes,generateRoutes,mixLeftMenus,setMixLeftMenus}
})// 非setup
export function usePermissionStoreHook() {return usePermissionStore(store)
}

4. api/menu

上面的 MenuAPI.getRoutes() 就是在 api/menu 里面定义的接口请求

import request from "@/utils/request";
import { MenuQuery, MenuVO, MenuForm, RouteVO } from "./model";class MenuAPI {/*** 获取路由列表*/static getRoutes() {return request<any, RouteVO[]>({url: "/api/v1/menus/routes",method: "get",});}// ... 其它接口
export default MenuAPI;

5. plugins/permission

这个文件内也是一些权限配置,按钮鉴权,路由守卫都放在这里面了,主要看 setupPermission 中的 router.addRoute(route) 跳转时会把动态路由塞到原本路由表内

import router from '@/router'
import { useUserStore, usePermissionStore } from '@/store'
import NProgress from '@/utils/nprogress'
import { RouteRecordRaw } from 'vue-router'
import { TOKEN_KEY } from '@/enums/CacheEnum'// 是否有权限
export function hasAuth(value: string | string[], type: 'button' | 'role' = 'button') {const { roles, perms } = useUserStore().user//「超级管理员」拥有所有的按钮权限if (type === 'button' && roles.includes('ROOT')) {return true}const auths = type === 'button' ? perms : rolesreturn typeof value === 'string'? auths.includes(value): auths.some(perm => {return value.includes(perm)})
}export function setupPermission() {// 白名单路由const whiteList = ['/login', '/404']router.beforeEach(async (to, from, next) => {NProgress.start()const hasToken = localStorage.getItem(TOKEN_KEY)if (hasToken) {if (to.path === '/login') {// 如果已登录,跳转首页next({ path: '/' })NProgress.done()} else {const userStore = useUserStore()const hasRoles = userStore.user.roles && userStore.user.roles.length > 0if (hasRoles) {// 未匹配到任何路由,跳转404if (to.matched.length === 0) {from.name ? next({ name: from.name }) : next('/404')} else {next()}} else {const permissionStore = usePermissionStore()try {const { roles } = await userStore.getUserInfo()const accessRoutes = await permissionStore.generateRoutes(roles)accessRoutes.forEach((route: RouteRecordRaw) => {router.addRoute(route)})next({ ...to, replace: true })} catch (error) {// 移除 token 并跳转登录页await userStore.resetToken()next(`/login?redirect=${to.path}`)NProgress.done()}}}} else {// 未登录可以访问白名单页面if (whiteList.indexOf(to.path) !== -1) {next()} else {next(`/login?redirect=${to.path}`)NProgress.done()}}})router.afterEach(() => {NProgress.done()})
}

差不多是这样的,大概页面就这样了
在这里插入图片描述

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

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

相关文章

纷享销客一体化BI智能分析平台介绍

纷享销客BI智能分析平台是一款自助式敏捷BI&#xff0c;无缝继承纷享销客PaaS平台的对象数据、对象关系、功能权限体系与数据权限体系&#xff0c;用户通过简单的拖拽点选即可实现灵活定义分析模型和可视化自助分析&#xff0c;零技术门槛快速上手&#xff0c;面向全员各类角色…

深度学习 --- stanford cs231 编程作业(assignment1,Q2: SVM分类器)

stanford cs231 编程作业之SVM分类器 写在最前面&#xff1a; 深度学习&#xff0c;或者是广义上的任何学习&#xff0c;都是“行千里路”胜过“读万卷书”的学识。这两天光是学了斯坦福cs231n的一些基础理论&#xff0c;越往后学越觉得没什么。但听的云里雾里的地方也越来越多…

【学习笔记】MySQL(Ⅰ)

MySQL(Ⅰ) 1、 介绍 1.1、概述 1.2、MySQL 的优缺点 1.4、关系型数据库模型2、 基础篇 —— SQL(结构化查询语言) 2.1、通用语法 2.2、SQL 语句的分类 2.3、DDL 语句 2.3.1 数据库结构相关的语法 2.3.2 数据表相关的语…

Java实现俄罗斯方块游戏源代码(启动即可玩)

这是一个用Java Swing实现的俄罗斯方块游戏&#xff0c;具有经典的游戏机制和图形界面。游戏中&#xff0c;玩家需要旋转和移动不断下落的方块&#xff0c;使其填满一行来消除该行并得分。 该项目适合学习Java GUI编程、游戏开发基础以及面向对象编程&#xff08;OOP&#xff0…

【Git】分支管理 -- 详解

一、理解分支 分支就是科幻电影里面的平行宇宙&#xff0c;当你正在电脑前努力学习 C 的时候&#xff0c;另一个你正在另一个平行宇宙里努力学习 JAVA。 如果两个平行宇宙互不干扰&#xff0c;那对现在的你也没啥影响。不过&#xff0c;在某个时间点&#xff0c;两个平行宇宙…

【Angew】:催化材料中贵金属的最大效率-原子分散表面铂

图形摘要&#xff1a;通过在纳米结构 CeO2的 {100}“纳米袋”中稳定表面 Pt2物种&#xff08;见图&#xff09; &#xff0c;可以制备具有最高贵金属分散度的Pt-CeO2材料。此类材料可以大大减少催化剂所需的贵金属量。 摘要&#xff1a;贵金属Pt是催化领域用途最广泛的元素&am…

【JS】JS高阶函数——reduce()用法详解总结。你不得不知道的数组reduce高级用法!

reduce用法详解总结 1.reduce语法说明1.1 方法介绍1.2 参数说明1.3 执行机制1.4 简单示例&#xff1a;数组求和 2. 高级用法2.1 权重求和2.2 代替some和every2.3 数组扁平2.4 数组去重2.5 字符统计和单词统计2.6 数组成员特性分组2.7 数字千分化 reduce函数是一个神奇的函数 1.…

C++ Qt实现http url启动本地应用程序

更多Qt文章,请访问《深入浅出C++ Qt开发技术专栏》:https://blog.csdn.net/yao_hou/category_9276099.html 我们在使用腾讯会议时经常会通过http链接打开本地的腾讯会议,例如下图: 打开会议发起人给的链接,会出现一个网页,然后点击加入会议就会启动本地的腾讯会议,本篇…

msvcp140_1.dll丢失怎么修复,这四种修复方法可轻松搞定

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140_1.dll丢失”。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;本文将介绍5种常见的解决方法&#xff0c;帮助大家快速恢复应用程序的正常运行。 一&a…

OCP 备份 OceanBase集群

注:OCP版本为4.2.1,OceanBase版本为 社区版4.2.1.0 手动备份 进行合并 在手动进行备份数据之前&#xff0c;建议进行一次OB集群合并(不影响业务的前提下)&#xff0c;关于合并的概念请参考OB官网。 点击进入要备份的OB集群 点击左侧工具栏中的 合并管理&#xff0c;在 基本信息…

App UI 风格:独具一格,令人惊艳

App UI 风格&#xff1a;独具一格&#xff0c;令人惊艳

交叉导轨在医疗设备上的作用!

随着医疗器械行业的需求逐步增长&#xff0c;交叉导轨给医疗器械行业带来了广阔的发展前景。作为重要的精密传动元件&#xff0c;交叉导轨具有寿命长、高精度、高刚性、高耐腐蚀性和高稳定性等优点&#xff0c;满足精密仪器上对产品的高要求使用场景。 在医疗设备领域中交叉导轨…

LeetCode刷题 | Day 3 分割等和子集(Partition Equal Subset Sum)

LeetCode刷题 | Day 3 分割等和子集(Partition Equal Subset Sum) 文章目录 LeetCode刷题 | Day 3 分割等和子集(Partition Equal Subset Sum)前言一、题目概述二、解题方法2.1 动态规划思想2.1.1 思路讲解2.1.2 伪代码 + 逐步输出示例2.1.3 Python代码如下2.1.4 C++代码如…

电脑显示找不到steam_api.dll,无法继续执行代码的详细解决办法

电脑显示找不到steam_api.dll,无法继续执行代码&#xff1f;其实会造成这种原因&#xff0c;注意是由于操作不当或者是中了病毒而导致的&#xff0c;我们想要解决steam_api.dll的丢失还是比较简单的&#xff0c;目前有多种的steam_api.dll修复方法&#xff0c;今天我们就来详细…

MySQL数据库常见工具的基础使用_1

在上一篇文章中提到了对MySQL数据库进行操作的一些常见工具 mysqlcheck mysqlcheck是一个用于数据库表的检查&#xff0c;修复&#xff0c;分析和优化的一个客户端程序 分析的作用是查看表的关键字分布,能够让sql生成正确的执行计划(支持InnoDB,MyISAM,NDB)检查的作用是检查…

前端逆向之下载canvas引用的图片

前端逆向之下载canvas引用的图片 一、来源二、解决三、如果在Network这里也找不到呢&#xff1f; 一、来源 当我们用dom检查器的时候无法选中想要扒下来的图片&#xff0c;只能选中canvas&#xff0c;这种时候该怎么办呢&#xff1f; 二、解决 这个时候应该换个脑子&#xf…

AI菜鸟向前飞 — LangChain系列之十六 - Agent系列:从现象看机制(下篇)一款“无需传递中间步骤“的Agent

前言 AI菜鸟向前飞 — LangChain系列之十四 - Agent系列&#xff1a;从现象看机制&#xff08;上篇&#xff09; AI菜鸟向前飞 — LangChain系列之十五 - Agent系列&#xff1a;从现象看机制&#xff08;中篇&#xff09;一个Agent的“旅行” 回顾前两篇文章&#xff0c;大家会…

endnote IEEEtran 参考文献 输出Latex

文章目录 参考文献Latex1. 新建格式1.1 新建BibTeX Export样式文件1.2 保存自定义文献格式 2 修改2.1 修改Journal Names 为简写2.2 修改Author Lists2.3 修改 模版 Templates 3. 特殊字符作者名字标题 4. 增加期刊简写4.1 删除已有简写的Term Lists 4.2 下载最新的Term LIsts4…

ApsaraMQ Copilot for RocketMQ:消息数据集成链路的健康管家

作者&#xff1a;文婷 引言 如何正确使用消息队列保证业务集成链路的稳定性&#xff0c;是消息队列用户首要关心的问题。ApsaraMQ Copilot for RocketMQ 从集成业务稳定性、成本、性能等方面帮助用户更高效地使用产品。 背景 消息队列产品通过异步消息的传递&#xff0c;来…

Linux shell编程学习笔记55:hostname命令——获取或设置主机名,显示IP地址和DNS、NIS

0 前言 2024年的网络安全检查又开始了&#xff0c;对于使用基于Linux的国产电脑&#xff0c;我们可以编写一个脚本来收集系统的有关信息。其中主机名也是我们要收集的信息之一。 1. hostname命令 的功能、格式和选项说明 我们可以使用命令 hostname --help 来查看hostname命令…