vue3后台管理系统权限路由的实现

最近做管理系统的时候,需要实现不同用户登陆所展示的菜单不同,查了不少帖子,总结下实现的步骤:

1.在router/index.js的代码:

import { createRouter, createWebHistory,createWebHashHistory } from 'vue-router'
import NotFound from '@/pages/404/404.vue'
const routes = [{ path: "/", component: () => import('@/pages/manage/manage.vue') },  // 登录页{ path: "/login", component: () => import('@/pages/login/login.vue') },  // 登录页{path: "/manage", name: 'Manage', component: () => import('@/pages/manage/manage.vue')}, { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
]
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes:routes
})export default router

2.在main.js同目录建立permission.js

// 说明:路由守卫文件
import axios from "axios";
// 引入
import router from "./router";
// 判断用户无token 返回登录页提示有用
import { ElMessage } from 'element-plus';
let hasGetUserInfo = false;
// 一、前置守卫
router.beforeEach(async (to, from, next) => {const token = localStorage.getItem('token')if(!token && to.path !== '/login') return next('/login')if(token && to.path =='/login') {return next(from.path)}if(token && !hasGetUserInfo) {const res = await axios.get('https://mock.mengxuegu.com/mock/639d71742e0f396e51a5c945/example/menus')console.log(res)const ret = res.data.data.list;createRouters(ret);hasGetUserInfo =truereturn next(to.path);}next()
})// 动态路由获取:注:之后完善项目直接考虑在登录的时候直接获取
// 直接缓存在 pinia 里
// 这里直接取数据,不请求// const data = localStorage.getItem('routes')
// const allData = JSON.parse(data)
// function addRoutes() {
//     // 1、后端数据
//     createRouters(allData)
// }
// 拼接路由
function createRouters(result) {result.forEach((item) => {// 1、类型为0的菜单,子路由不为空,将子路由添加到manage里if (item.menuType === '0' && item.children.length > 0) {item.children.forEach((children) => {createRouterTemplate('Manage', children);})}// 2、menuType == 1, 子路由为空if (item.menuType === '1' && item.children.length === 0) {createRouterTemplate('Manage', item);}// 3、递归层级if (item.children.length > 0) {createRouters(item.children);}});
}
// 把router 的动态路由进行封装
function createRouterTemplate(fatherRouter, item) {router.addRoute(fatherRouter, {path: item.path,name: item.name,meta: {title: item.meta.title, // 面包屑用requiresAuth: item.meta.requiresAuth,roles: item.meta.roles,breadcrumb: item.meta.breadcrumb,keepAlive: item.meta.keepAlive},// /* @vite-ignore */ :处理vite动态导入的警告component: () => import(/* @vite-ignore */ `./views${item.component}`)})}
// 二、后置守卫
router.afterEach((to) => {// 标签抬头})// main.js 导入的为这个router
export default router

3.然后在mian.js引入:

import { createApp } from 'vue'
import { createPinia } from 'pinia'import App from './App.vue'
import router from './permission'; // 现router
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'const app = createApp(App)app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')

4.后端返回数据格式:


[{"id": "1","name": "Home","path": "/home","component": "/home/index.vue","menuType": "1","icon": "Discount","sort": 0,"meta": {"title": "系统首页","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": []},{"id": "2","name": "System","path": "/system","component": "/system/index.vue","menuType": "0","icon": "Operation","sort": 0,"meta": {"title": "系统管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": [{"id": "211","name": "User","path": "/user","component": "/user/index.vue","menuType": "1","icon": "user","sort": 0,"meta": {"title": "用户管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": []},{"id": "222","name": "Menu","path": "/menu","component": "/menu/index.vue","menuType": "1","icon": "Menu","sort": 0,"meta": {"title": "菜单管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": []},{"id": "223","name": "Role","path": "/role","component": "/role/index.vue","menuType": "1","icon": "Avatar","sort": 0,"meta": {"title": "角色管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": []}]},{"id": "3","name": "Log","path": "/log","component": "/log/index.vue","menuType": "1","icon": "Notebook","sort": 0,"meta": {"title": "日志管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": []},{"id": "4","name": "Study","path": "/study","component": "/study/index.vue","menuType": "0","icon": "Notebook","sort": 0,"meta": {"title": "学习管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": [{"id": "441","name": "StudyUser","path": "/studyUser","component": "/study/user/index.vue","menuType": "0","icon": "Notebook","sort": 0,"meta": {"title": "用户管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": [{"id": "4441","name": "Student","path": "/student","component": "/study/user/student/index.vue","menuType": "1","icon": "Notebook","sort": 0,"meta": {"title": "学生管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": []},{"id": "4442","name": "Teacher","path": "/teacher","component": "/study/user/teacher/index.vue","menuType": "1","icon": "Notebook","sort": 0,"meta": {"title": "教师管理","requiresAuth": null,"roles": [],"breadcrumb": [{}],"keepAlive": null},"children": []}]}]}
]

5.首页的代码:

<script setup>
import { RouterView ,useRouter} from 'vue-router';
import AsideMenu from '@/components/AsideMenu.vue'
const router = useRouter()
const logout = ()=>{localStorage.removeItem('token')router.replace('/login')
}
</script>
<template><div class="common-layout"><el-container style="height: 100vh;"><el-aside width="200px"><AsideMenu></AsideMenu></el-aside><el-main><div><el-button @click="logout">推出登陆</el-button></div><RouterView /></el-main></el-container></div></template>

6.组件AsideMenu.vue的代码:

<template><el-menu router :default-active="$route.path" :class="'menu-left'" :default-openeds="openedsArr" text-color="#fff"><LeftSubMenu :menuData="treeMenu"></LeftSubMenu></el-menu>
</template><script setup>
import LeftSubMenu from "./LeftSubMenu.vue";
import { computed } from "vue";
import { useRouter } from "vue-router";
import { onMounted,ref } from "vue";const treeMenu = ref([])const openedsArr = treeMenu.value.map((item) => {return item.path;
});onMounted(()=>{const data = localStorage.getItem('menuData')treeMenu.value = JSON.parse(data)
})</script><style scoped>
.menu-left {flex: 1;padding: 0 8px;border-right: none;background: none;
}.menu-left:deep(.el-menu),
.menu-left:deep(.el-sub-menu__title:hover) {background: none;
}.menu-left:deep(.el-menu-item),
.menu-left:deep(.el-sub-menu__title) {height: 36px;margin-bottom: 4px;border-radius: 4px;color: var(--text-main-color) !important;
}.menu-left:deep(.el-menu-item:hover .icon),
.menu-left:deep(.el-menu-item.is-active .icon) {filter: invert(100%);-webkit-filter: invert(100%);
}.menu-left:deep(.el-menu-item:hover),
.menu-left:deep(.el-menu-item.is-active) {color: #ffffff !important;background-color: #eecece;
}
</style>

7.组件LeftSubMenu.vue的代码

<template><template v-for="item in props.menuData"><el-sub-menu :key="item.path" v-if="item.children && item.children.length > 0" :index="item.path"><template #title><el-icon><component :is="item.icon"></component></el-icon><span>{{ item.meta.title }}</span></template><LeftSubMenu :menuData="item.children"></LeftSubMenu></el-sub-menu><el-menu-item :key="item.id" v-else :index="item.path" :disabled="item.disabled"><template #title><!-- <img class="icon pd-r-10" :src="item.icon" /> --><el-icon><component :is="item.icon"></component></el-icon><span>{{ item.meta.title }}</span></template></el-menu-item></template>
</template><script setup>
import LeftSubMenu from "./LeftSubMenu.vue";
import { computed, onMounted } from "vue";
import { useRouter } from "vue-router";const props = defineProps({menuData: {type: Array,default: [],},
});onMounted(() => {console.log(props.menuData, "Item打印数据");
});const curRoute = computed(() => {const router = useRouter();const { path } = router.currentRoute.value;return path;
});
</script>

这样就实现该功能,登陆页面就是登陆保存token的操作。

感谢VueRouter4 - 动态路由刷新变空白或404_vue刷新页面后路由匹配到空白-CSDN博客,Vue3+Vue-Router+Element-Plus根据后端数据实现前端动态路由——权限管理模块_vue3动态路由权限-CSDN博客

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

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

相关文章

基于SpringBoot+Vue交流和分享平台的设计与实现(源码+部署说明+演示视频+源码介绍)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

Apache zookeeper kafka 开启SASL安全认证

背景&#xff1a;我之前安装的kafka没有开启安全鉴权&#xff0c;在没有任何凭证的情况下都可以访问kafka。搜了一圈资料&#xff0c;发现有关于sasl、acl相关的&#xff0c;准备试试。 简介 Kafka是一个高吞吐量、分布式的发布-订阅消息系统。Kafka核心模块使用Scala语言开发…

【人工智能入门必看的最全Python编程实战(5)】

--------------------------------------------------------------------- 1.AIGC未来发展前景 未完持续… 1.1 人工智能相关科研重要性 拥有一篇人工智能科研论文及专利软著竞赛是保研考研留学深造以及找工作的关键门票&#xff01;&#xff01;&#xff01; 拥有一篇人工…

数据结构 第5章 树与二叉树(一轮习题总结)

数据结构 第5章 树与二叉树 5.1 树的基本概念5.2 二叉树的概念5.3 二叉树的遍历和线索二叉树5.4 树、森林5.5 树与二叉树的应用 5.1 树的基本概念&#xff08;3 4 7&#xff09; 5.2 二叉树的概念&#xff08;2 14 19 22&#xff09; 5.3 二叉树的遍历和线索二叉树 5.4 树、森林…

AIDD简介——分类和回归任务

&#x1f31e;欢迎来到AI生物医药的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f320;本阶段属于练气阶段&#xff0c;希望各位仙友顺利…

《ARM汇编与逆向工程 蓝狐卷 基础知识》

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

【JS】优化代码分支

判断条件很多时&#xff0c;会降低代码的可读性&#xff0c;例如下面这段代码 function fn(type){if(type 1){console.log(待把相思灯下诉)}else if(type 2){console.log(一缕新欢)}else if(type 3){console.log(旧恨千千缕)}else if(type 4){console.log(最是人间留不住)…

Ubuntu20下C/C++编程开启TCP KeepAlive

1、在linux下&#xff0c;测试tcp保活&#xff0c;可以使用tcp自带keepalive功能。 2、几个重要参数&#xff1a; tcp_keepalive_time&#xff1a;对端在指定时间内没有数据传输&#xff0c;则向对端发送一个keepalive packet&#xff0c;单位&#xff1a;秒 tcp_keep…

拌合楼内部管理系统开发(一)立个flag,开始做准备

前言&#xff1a;项目背景情况介绍 公司有意开发一套适合拌合楼的内部管理系统给到客户使用&#xff0c;接触过一家拌合楼行业内号称标杆的企业&#xff0c;去过参观学习的都觉得他们软件好用&#xff0c;但是从软件开发角度看&#xff0c;就是crud钉钉机器人无人值守。虽然公司…

Python语法糖

N u m P y NumPy NumPy的 n d i t e r nditer nditer nditer 是 NumPy 提供的一种多维迭代器&#xff0c;用于对多维数组进行迭代操作。它可以替代传统的嵌套循环&#xff0c;在处理多维数组时更加方便和高效。 迭代器可以按照不同的顺序遍历数组的元素&#xff0c;也可以控制…

npm install和npm install --save的区别

1、npm install XX 会把XX包安装到 node modules 目录中; 不会修改 package.json; 之后运行 npm instal1 命令时&#xff0c;不会自动安装XX; 2、npm install --save XX 会把XX包安装到 node_modules 目录中: 会在 package.json 的 dependencies 属性下添加XX; 之后运行…

JDK8和JDK11在Ubuntu18上切换(解决nvvp启动报错)

本文主要介绍JDK8和JDK11在Ubuntu18上切换&#xff0c;以供读者能够理解该技术的定义、原理、应用。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;计算机杂记 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人…

Redis列表:高效消息通信与实时数据处理的利器

Redis是一个强大的开源内存数据库&#xff0c;被广泛应用于缓存、会话存储、队列等各种场景中。在Redis中&#xff0c;列表&#xff08;List&#xff09;是一种非常重要的数据结构&#xff0c;它提供了存储、获取、操作有序元素集合的功能。本文将深入探讨Redis列表的特性、使用…

C++的类和对象(七):友元、内部类

目录 友元 友元函数 友元类 内部类 匿名对象 拷贝对象时的一些编译器优化 再次理解类和对象 友元 基本概念&#xff1a;友元提供了一种突破封装的方式&#xff0c;有时提供了便利&#xff0c;但是友元会增加耦合度&#xff0c;破坏了封装&#xff0c;所以友元不宜多用&…

[嵌入式系统-39]:龙芯1B 开发学习套件 -10-PMON启动过程Sstart.S详解

目录 一、龙芯向量表与启动程序的入口&#xff08;复位向量&#xff09; 1.1 复位向量&#xff1a; 1.2 代码执行流程 1.3 计算机的南桥 VS 北桥 二、PMON代码执行流程 三、Start.S详解 3.1 CPU初始化时所需要的宏定义 &#xff08;1&#xff09;与CPU相关的一些宏定义…

北斗卫星在桥隧坡安全监测领域的应用及前景展望

北斗卫星在桥隧坡安全监测领域的应用及前景展望 北斗卫星系统是中国独立研发的卫星导航定位系统&#xff0c;具有全球覆盖、高精度定位和海量数据传输等优势。随着卫星导航技术的快速发展&#xff0c;北斗卫星在桥隧坡安全监测领域正发挥着重要的作用&#xff0c;并为相关领域…

有关于Docker(容器),Image(镜像)部署等名词含义

理解 Docker、镜像和代码修改之间的关系和逻辑可以通过以下步骤来解释&#xff1a; 开发环境设置&#xff1a; 在开发阶段&#xff0c;开发人员通常会编写应用程序的代码。Docker 提供了一种将应用程序与其依赖项打包在一起的方法&#xff0c;称为 Docker 镜像。这个镜像可以包…

element-plus 完成下拉切换功能

项目场景&#xff1a; element-plus element-plus 完成下拉切换功能&#xff0c;选用了popover 组件去进行样式修改&#xff0c;本来大概是要实现下面这样的样式效果&#xff0c;没想到调整的时候&#xff0c;这个选择的高亮模块总是超出。 实现效果&#xff1a; 解决方案&am…

android HAL层崩溃排查记录

要最近在调试系统HDMI CEC功能时&#xff0c;遇到一个奇怪的崩溃问题&#xff0c;这边记录下。 初步分析 先上日志&#xff1a; --------- beginning of crash 03-06 10:48:25.503 1133 1133 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** **…

微信小程序 - 基于scroll view 实现下拉刷新

简介 本文会基于scroll view 实现下拉刷新效果&#xff0c;在下拉的时候会进入loading状态。 实现效果 效果如上图所示&#xff0c;在下拉到底部时候&#xff0c;会出现loading条&#xff0c;在处理完成后loading条消失。 具体代码 布局 <scroll-view scroll-y style&qu…