最近做管理系统的时候,需要实现不同用户登陆所展示的菜单不同,查了不少帖子,总结下实现的步骤:
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 =true return 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.首页的代码:
推出登陆
6.组件AsideMenu.vue的代码:
7.组件LeftSubMenu.vue的代码
{{ item.meta.title }} {{ item.meta.title }}
这样就实现该功能,登陆页面就是登陆保存token的操作。
感谢VueRouter4 - 动态路由刷新变空白或404_vue刷新页面后路由匹配到空白-CSDN博客,Vue3+Vue-Router+Element-Plus根据后端数据实现前端动态路由——权限管理模块_vue3动态路由权限-CSDN博客