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

vue3权限管理——(路由权限)动态路由设置

1.大概思路

  1. 设置基础路由login和home等页面;
  2. 登录后从后端获取user,token,rights等数据,并将数据同时存储到vuex和sessionStorage中
  3. 将后端获取的权限数据(作为不同用户显示不同菜单及不同路由的依据)和路由页面进行映射;
  4. 写公共方法添加动态路由;
  5. 在路由全局守卫中判断是否已添加过动态路由,如果已添加直接next()未添加调用添加动态路由方法,并且放行(next({ ...to, replace: true }););
  6. 添加动态路由位置第二种方法:全局路由中只负责判断是否有动态路由和放行,调用添加动态路由方法,在登录后立即调用,且以防页面手动刷新时进行404页面,需要在App.vue的create()方法中再次调用

2.设置基础路由,login页面,Home页面等

//route.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [{ name: 'Login', path: '/login', component: Login },{name: 'Home',path: '/',component: Home,// 到home页面后直接跳转到excelPreview页面redirect: '/uploadSpec?active=0',meta: {authentication: true},// 整个页面为Home,如果想要点击el-aside左侧菜单,将对应路由内容显示在el-main区域,需要将其他路由路径设置为Home的子路径,且path前没有/children: [{name: 'UploadSpec',path: 'uploadSpec',title: '上传spec',component: UploadSpec,// 组件内传参meta: {keepAlive: true,authentication: true,// 用于设置tab名title: '上传spec',}},]},// vue3不再使用path:'*'正则匹配,而是使用/pathMatch(.*)*或/pathMatch(.*)或/catchAll(.*)// { name: 'NotFound', path: '/404', component: NotFound },// { path: '/:pathMatch(.*)', redirect: '/404' },
];const router = createRouter({history: createWebHistory(),routes,
});

2.从后端获取菜单权限数据并设置到vuex和sessionStorage中

这里使用mock模拟后端返回数据

//mock/user.js
import Mock from 'mockjs'const users = [{'id': 1, path:'/uploadSpec','authName': "上传spec", 'icon': '',children:[]},{'id': 2, path:'/showSpec', 'authName': "Spec预览", 'icon': '',children:[]},{'id': 3, path:'/generateTxt', 'authName': "生成测试数据", 'icon': '',children:[]},{'id': 4, path:'/generateCronjob', 'authName': "生成转码程序", 'icon': '',children:[]},{'id': 5, path:'/pdfCompare', 'authName': "PDF文档对比", 'icon': '',children:[]},{'id': 6, path:'/resourceUpdate', 'authName': "资源更新管理", 'icon': '',children:[]},{'id': 7, path:'/generateTestCase', 'authName': "自动生成ST/SIT案例", 'icon': '',children:[]},{'id': 8, path:'/userManagement', 'authName': "用户管理", 'icon': 'User'},
]Mock.mock("/user/login", Mock.mock({"code": 200,"success": true,"data": {users: users,"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsIm5pY2tOYW1lIjoi6LaF566hIiwiaWNvbiI6IiIsInJvbGVJZCI6MSwic3ViIjoiYWRtaW4iLCJleHAiOjE2OTI3NzMzNTMsImp0aSI6ImZkNmVkOWZiMjdiYzQxODg5OWRmYmYzNzhlMTMzZmQ0In0.APGpN-i2edKwPQA52LP10aDEM2DZi7G71k8f_njGcpE"}
})
)Mock.mock("/user/me", Mock.mock({"code": 200,"success": true,"data": {"id": 1,"userName": "admin","nickName": "超管","icon": "","roleId": 1,"rights": users,}
})
)

3.登录后将数据存到vuex和sessionStorage中

//Login.vue           await this.$store.dispatch("user/login", {...this.user});

//store/user/user.js
import * as api from '@/api/api'
import { ElMessage } from 'element-plus'const state = () => {return {user:JSON.parse(sessionStorage.getItem("user") || '{}'),rights: JSON.parse(sessionStorage.getItem("rights") || '[]')}
}const getters = () => {}const actions = {// 注意async位置和箭头函数写法login: async({ commit }, user) => {// 调用登录接口try {let result = await api.login(user);if (result.data.code === 200) {sessionStorage.setItem("token", result.data.data.token);// 调用获取user信息接口let loginUser = await api.getLoginUser();// 调用mutations的login方法if (loginUser.data.code === 200) {commit('login', loginUser.data.data);} else {ElMessage.error("登录失败:用户信息获取失败");}} else {ElMessage.error("登录失败:" + result.data.errorMsg);}} catch (error) {throw error;}},
}const mutations = {initUser: (state) => {// 从localStorage中获取数据设置进user中,否则通过刷新页面时,获取不到state中的user信息state.user = JSON.parse(sessionStorage.getItem("loginUser"));},login: (state, user) => {// 登录成功后将user信息存到state中,且缓存到localStorage中state.user = user;state.rights = user.rights;sessionStorage.setItem("loginUser", JSON.stringify(user));sessionStorage.setItem("rights", JSON.stringify(user.rights));},
}export default {namespaced: true,state,getters,actions,mutations
}

4.设置菜单权限数据和路由的映射

注意此处routeMapping的key和uploadSpecRule的path以及和后端返回数据rights的user.js的path必须一致;且路径必须有 "/"

const uploadSpecRule = {name: 'UploadSpec',path: '/uploadSpec',title: '上传spec',component: UploadSpec,meta: {keepAlive: true,authentication: true,title: '上传spec',}
};const showSpecRule = {name: 'ExcelPreview',path: '/showSpec',title: 'Spec预览 | 生成测试数据',component: ExcelPreview,meta: {keepAlive: true,authentication: true,title: 'Spec预览',}
};const generateTxtRule = {name: 'GenerateTxt',path: '/generateTxt',title: '生成测试数据',component: GenerateTxt,meta: {keepAlive: true,authentication: true,title: '生成测试数据',}
};
const generateCronjobRule = {name: 'GenerateCronjob',path: '/generateCronjob',title: '生成转码程序',component: GenerateCronjob,meta: {keepAlive: true,authentication: true,title: '生成转码程序',}
};
const pdfCompareRule = {name: 'PDFCompare',path: '/pdfCompare',title: 'PDF文档对比',component: PDFCompare,meta: {keepAlive: true,authentication: true,title: 'PDF文档对比',}
};
const resourceUpdateRule = {name: 'ResourceUpdate',path: '/resourceUpdate',title: '资源更新管理',component: ResourceUpdate,meta: {keepAlive: true,authentication: true,title: '资源更新管理',}
};
const generateTestCaseRule = {name: 'GenerateTestCase',path: '/generateTestCase',title: '自动生成ST/SIT案例',component: GenerateTestCase,meta: {keepAlive: true,authentication: true,title: '自动生成ST/SIT案例',}
};
const userManagementRule = {name: 'UserManagement',path: '/userManagement',title: '用户管理',component: UserManagement,meta: {keepAlive: true,authentication: true,title: '用户管理',}
};const routeMapping = {'/uploadSpec': uploadSpecRule,'/showSpec': showSpecRule,'/generateTxt': generateTxtRule,'/generateCronjob': generateCronjobRule,'/pdfCompare': pdfCompareRule,'/resourceUpdate': resourceUpdateRule,'/generateTestCase': generateTestCaseRule,'/userManagement': userManagementRule,
}

5.设置可导出添加动态路由公共方法

export const initDynamicRoutes = async () => {const rightsList = Store.state.user.rights;;rightsList.length > 0 && rightsList.forEach(item => {if (item.path) {const temp = routeMapping[item.path];router.addRoute("Home", temp);}});router.addRoute( { name: 'NotFound', path: '/404', title:"页面不存在",component: NotFound });router.addRoute( { path: '/:pathMatch(.*)', redirect: '/404' });
}

5.全局路由守卫中鉴权及激活动态路由

注意在vue-router4.X中,动态路由主要通过两个函数实现。router.addRoute() 和 router.removeRoute()。它们注册一个新的路由,也就是说,如果新增加的路由与当前位置相匹配,就需要你用 router.push() 或 router.replace() 来手动导航,才能显示该新路由。

也就是说以前的rouer.addRoutes()添加即可使用动态路由的方式不行了

// 路由守卫鉴权处理
router.beforeEach(async (to, from, next) => {let token = sessionStorage.getItem("token");let isToken = !!token;let loginUser = Store.state.user.user;if (isToken) {if (loginUser) {// 如果是login,且已经登录了直接跳转到home页面if (to.name === "Login") return next();// 已经设置过动态路由直接放行,没有则需要通过手动调用 router.replace()进行路由显示if (isDynamic) {next();} else {await initDynamicRoutes();isDynamic = true;next({ ...to, replace: true });}} else {sessionStorage.clear();next("/login");}} else {isDynamic = false;next();}
});

6.第二种方法激活动态路由——在Login.vue和App.vue中调用

 这种方式不会每次路由都调用一次添加动态路由方法,个人觉得这种方式性能比较好

//App.vue
import { initDynamicRoutes } from "@/route/route"
export default {name: 'App',created(){initDynamicRoutes();}
}
</scri
//Login.vuetry {await this.$store.dispatch("user/login", {...this.user});//登录成功后,根据用户的rights动态添加路由initDynamicRoutes();this.$router.push({ name: "Home" });} catch (e) {}

7.注意点:

7.1 必须使用router.addRoute()方法进行添加动态路由

添加动态路由方法中,是使用router.addRoute()方法进行添加,Home表示将路由嵌套在Home页面下

rightsList.length > 0 && rightsList.forEach(item => {if (item.path) {const temp = routeMapping[item.path];router.addRoute("Home", temp);}});

我试过之前的添加方法已经不能成功添加动态路由了

const currentRoutes = router.options.routes;rightsList.length > 0 && rightsList.forEach(item => {if (item.path) {const temp = routeMapping[item.path];currentRoutes[1].children.push(temp);}});

7.2 错误页面添加时机

错误页面必须也使用动态添加方法,并且在路由动态添加完成后再添加,否则如果在基础路由中定义错误页面,那么每次点击路由都会首先找路由,没找到就会匹配到错误页面,从而跳转到错误页面

rightsList.length > 0 && rightsList.forEach(item => {if (item.path) {const temp = routeMapping[item.path];router.addRoute("Home", temp);// currentRoutes[1].children.push(temp);}});router.addRoute( { name: 'NotFound', path: '/404', title:"页面不存在",component: NotFound });router.addRoute( { path: '/:pathMatch(.*)', redirect: '/404' });

7.3判断动态路由是否启用的标识

如果直接next()会找不到动态路由,而直接next({ ...to, replace: true });会导致永远去找动态路由

使用标识后,如果有动态路由就加载动态路由,没有直接放行

if (isToken) {if (loginUser) {// 如果是login,且已经登录了直接跳转到home页面if (to.name === "Login") return next();// 已经设置过动态路由直接放行,没有则需要通过手动调用 router.replace()进行路由显示if (isDynamic) {next();} else {// await initDynamicRoutes();isDynamic = true;next({ ...to, replace: true });}} else {sessionStorage.clear();next("/login");}} else {isDynamic = false;next();}

7.4警告:[Vue Router warn]: No match found for location with path "/generateCronjob"

以7.2的方式,在动态添加完其他路由后,再添加错误页面就能成功导到不同路由页面,但是警告依然会存在

相关文章:

vue3权限管理——(路由权限)动态路由设置

1.大概思路 设置基础路由login和home等页面&#xff1b;登录后从后端获取user,token,rights等数据&#xff0c;并将数据同时存储到vuex和sessionStorage中将后端获取的权限数据&#xff08;作为不同用户显示不同菜单及不同路由的依据&#xff09;和路由页面进行映射&#xff1…...

小程序开发之登录授权

小程序开发登录授权流程 看懂这张图登录授权就没问题了&#xff08;哈哈哈哈哈&#xff09; 说明&#xff1a; 调用 wx.login() 获取 临时登录凭证code &#xff0c;并回传到开发者服务器。 调用 auth.code2Session 接口&#xff0c;换取 用户唯一标识 OpenID 和 会话密钥 sess…...

批量根据excel数据绘制折线图

要批量根据Excel数据绘制折线图&#xff0c;可以使用数据处理和图表绘制软件&#xff0c;例如Microsoft Excel或Python中的Matplotlib库。以下是两种方法&#xff1a; 1. 使用Microsoft Excel&#xff1a; - 打开Excel并导入包含数据的工作表。 - 选择需要绘制折线图的数…...

无锁并发:探秘CAS机制的魔力

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; 无锁并发&#xff1a;探秘CAS机制的魔力 ⏱️ 创作时间&#xff1a; 2…...

iOS App签名与重签名:从开发者证书到重新安装运行

前文回顾&#xff1a; iOS脱壳技术&#xff08;二&#xff09;&#xff1a;深入探讨dumpdecrypted工具的高级使用方法 iOS逆向&#xff1a;越狱及相关概念的介绍 在本文中&#xff0c;我们将详细介绍iOS应用的签名过程&#xff0c;包括开发者证书的种类、证书与App ID、Provisi…...

vue项目,如何修改Element-Plus等UI组件库的样式,三种方式搞定!!!

前言 我们在学习和使用组件库构建页面的时候&#xff0c;时常会遇到这样的问题。 即&#xff0c;尽管组件库已经提供了较多的功能&#xff0c;来帮助我们构建自定义的效果&#xff0c;但有时仍不能使我们满意。 这个时候我们就不得不修改UI库的样式&#xff0c;来达到想要的状…...

httpd协议与apache

1.http 相关概念 HTTP是处于应用层的协议&#xff0c;使用TCP传输层协议进行可靠的传送。因此&#xff0c;需要特别提醒的是&#xff0c;万维网是基于因特网的一种广泛因特网应用系统&#xff0c;且万维网采用的是HTTP&#xff08;80/TCP&#xff09;和 HTTPS&#xff08;443/…...

Go 自学:文件的写入和读取

首先&#xff0c;使用os.Create()函数建立一个文件。 接着&#xff0c;使用io.WriteString()函数将内容写入文件。 最后&#xff0c;使用os.ReadFile()函数读取文件内容。 注意&#xff0c;这里读取的文件内容是data byte&#xff0c;我们需要使用string()函数将其转换为字符串…...

py 项目上线centos

1 服务器py版本 ps -ef|grep python|grep -v grep 2 2.x版本 安装 PyMySQL pip install PyMySQL0.9.3 3 后台运行py文件 nohup python down.py 1 > log.log 2>&1 & 这个命令将 down.py 程序放入后台运行&#xff0c; 同时将 stdout 输出到 log.log 文件中&…...

【git】would clobber existing tag 报错解决

问题 在用vscode的Git去pull代码的时候git弹窗报错&#xff0c;查看报错日志发现以下内容&#xff1a; > git pull --tags origin feature/xxx-2.0.0 From 173.110.11.22:VV-WORK-FE/vv-desktop* branch feature/xxx-2.0.0 -> FETCH_HEAD! [rejected] …...

Python OCR 使用easyocr库将图片中的文章提取出来

Python OCR 使用easyocr库将图片中的文章提取出来 初环境内容步骤一&#xff1a;安装easyocr库步骤二&#xff1a;导入必要的库步骤三&#xff1a;创建OCR阅读器对象步骤四&#xff1a;指定要识别的图片路径步骤五&#xff1a;执行OCR识别并提取文章内容步骤六&#xff1a;遍历…...

门禁系统忘记登入密码,现在更换电脑如何迁移旧电脑门禁系统的数据

环境&#xff1a; ivms-4200 v3.10.0.6_c 问题描述&#xff1a; 门禁系统忘记登入密码,现在更换电脑如何迁移旧电脑门禁系统的数据&#xff0c;旧电脑记住密码&#xff0c;忘了密码和密保了 解决方案&#xff1a; 1.前往海康官网下载4200客户端&#xff0c;在新电脑上安装 …...

初试Eureka注册中心

Eureka是spring cloud中的一个负责服务注册与发现的组件。遵循着CAP理论中的A(可用性)P(分区容错性)。一个Eureka中分为eureka server和eureka client。其中eureka server是作为服务的注册与发现中心。 搭建eureka服务 引入eureka依赖 引入SpringCloud为eureka提供的starter依…...

【趣味随笔】怎么维护自己的电脑?

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

element 下拉组件获取对象

// 选择数据user:[{name:"小白",id:1,money:"100",love:"蛋糕"},{name:"小黑",id:2,money:"200",love:"奶茶"},{name:"小红",id:3,money:"300",love:"烧烤"},] <div><el…...

IDEA下SpringBoot指定环境、配置文件启动

1、idea下的SpringBoot启动&#xff1a;指定配置文件 Springboot项目有如下配置文件 主配置文件application.yml&#xff0c; 测试环境&#xff1a;application-test.yml 生产环境&#xff1a;application-pro.yml 开发环境&#xff1a;application-dev.yml 1.1.配置文件…...

python可视化matplotlib——绘制正弦和余弦

这是一个使用matplotlib库绘制正弦和余弦函数曲线的代码示例。代码中导入了需要的库&#xff0c;并设置了x轴和y轴的标签字体为华文楷体。然后&#xff0c;使用numpy生成一组x轴上的值t&#xff0c;并使用正弦函数生成对应的y轴值s&#xff0c;再使用余弦函数生成对应的y轴值z。…...

Day48|leetcode 198.打家劫舍、213.打家劫舍II、打家劫舍|||

leetcode 198.打家劫舍 题目链接&#xff1a;198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 视频链接&#xff1a;动态规划&#xff0c;偷不偷这个房间呢&#xff1f;| LeetCode&#xff1a;198.打家劫舍_哔哩哔哩_bilibili 题目概述 你是一个专业的小偷&#xff0c;…...

Mysql001:Mysql概述以及安装

前言&#xff1a;本课程将从头学习Mysql&#xff0c;以我的工作经验来说&#xff0c;sql语句真的太重要的&#xff0c;现在互联网所有的一切都是建立在数据上&#xff0c;因为互联网的兴起&#xff0c;现在的数据日月增多&#xff0c;每年都以翻倍的形式增长&#xff0c;对于数…...

如何调用api接口获取到商品数据

要调用API接口获取商品数据&#xff0c;需要进行以下步骤&#xff1a; 1.确定API接口 首先需要确定要使用的API接口&#xff0c;可以通过搜索引擎或者相关文档来查找适合的API接口。以淘宝开放平台为例&#xff0c;可以使用淘宝的商品信息查询API接口来获取商品数据。 2.注册…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...