官网参考:https://router.vuejs.org/zh/guide/advanced/dynamic-routing.html
router/index.ts 配置代码,导出的router在main.ts中use即可。SystemDataStore.menus是用户登录后从后端获得的菜单数据。
router/index.ts 配置代码,导出的router在main.ts中use即可。SystemDataStore.menus是用户登录后从后端获得的菜单数据。
import { defineAsyncComponent } from 'vue' import { createRouter, createWebHistory } from 'vue-router' import { type route_data, type route_meta } from '@/common/interfaces' import pinia from '@/stores/store' import { useSystemDataStore } from '@/stores/index' import { getCookie } from '@/common/cookie' // SystemDataStore 可以在本文件中随意使用 const SystemDataStore = useSystemDataStore(pinia); //创建路由 const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', name: 'home', // 重定向到login 重定向和别名:https://router.vuejs.org/zh/guide/essentials/redirect-and-alias.html redirect: { name: 'login' }, }, { path: '/login', name: 'login', component: () => import('../views/Login.vue'), }, // 嵌套路由:https://router.vuejs.org/zh/guide/essentials/nested-routes.html { path: '/main', name: 'main', component: () => import('../views/Main.vue'), }, //注释掉原路由配置,改为动态路由。 // { // path: '/SysSetting', // name: 'SysSetting', // meta: { title: "系统设置" }, // children: [ // { // path: '/SysSetting/UserMgr', // name: 'UserMgr', // meta: { title: "用户管理" }, // children: [ // { // path: '/SysSetting/UserMgr/UserAccountMgr', // name: 'UserAccountMgr', // component: () => import('../views/SysSetting/UserMgr/UserAccountMgr.vue'), // meta: { title: "用户账户管理" }, // }, // { // path: '/SysSetting/UserMgr/UserAddressMgr', // name: 'UserAddressMgr', // component: () => import('../views/SysSetting/UserMgr/UserAddressMgr.vue'), // meta: { title: "用户地址管理" }, // }, // ], // }, // { // path: '/SysSetting/RoleMgr', // name: 'RoleMgr', // component: () => import('../views/SysSetting/RoleMgr.vue'), // meta: { title: "角色管理" }, // }, // { // path: '/SysSetting/MenuMgr', // name: 'MenuMgr', // component: () => import('../views/SysSetting/MenuMgr.vue'), // meta: { title: "菜单管理" }, // }, // { // path: '/SysSetting/ProductionMgr', // name: 'ProductionMgr', // component: () => import('../views/SysSetting/ProductionMgr.vue'), // meta: { title: "商品管理" }, // }, // ] // }, //注释掉,动态路由在刷新的时候尚未添加到routes中,会造成404. // 将匹配所有内容并将其放在 `$route.params.pathMatch` 下。 // { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('../views/NotFound.vue') }, ] }) //导航守卫 router.beforeEach(async (to, from, next) => { //用户登录后的token let token = getCookie('XSRF-TOKEN'); //标记是否已经添加过动态路由true/false let isLoadRouters = SystemDataStore.isLoadRouters; if (inWhiteList(to.path)) { next() } else { //用户已登录,加载用户信息、菜单信息、权限信息。 SystemDataStore.initData(); if (token && JSON.stringify(SystemDataStore.menus) !== '[]') { if (isLoadRouters) { // console.log('路由已添加,直接跳转到目标页面', router.getRoutes()); next() } else { //解决刷新页面空白 //console.log('重新加载路由,并跳转到目标页'); SystemDataStore.setIsLoadRouters(true) //添加动态路由 await generateRoutes(); // console.log('路由添加完毕,从新进入路由。', router.getRoutes()); next({ ...to, replace: true }) } } else { // console.log('无登录信息,跳转到登录页'); SystemDataStore.setIsLoadRouters(false) next(`/login`) } } }) //动态添加路由 const generateRoutes = () => { SystemDataStore.initData(); let _asyncRoutes = SystemDataStore.menus; if (_asyncRoutes == null) { return; } _asyncRoutes.forEach((menu1: any) => { if (menu1.children.length > 0) { menu1.children.forEach((menu2: any) => { if (menu2.children.length > 0) { menu2.children.forEach((menu3: any) => { let _asyncRoute3: any = menuToRoute(menu3); if (_asyncRoute3) { router.addRoute(_asyncRoute3) } }); } else { //二级 let _asyncRoute2: any = menuToRoute(menu2); if (_asyncRoute2) { router.addRoute(_asyncRoute2) } } }) } else { //一级 let _asyncRoute1: any = menuToRoute(menu1); if (_asyncRoute1) { router.addRoute(_asyncRoute1) } } }) } //将菜单转换成router可以识别的路由 const menuToRoute = (menu: any) => { if (!menu.url) { return null; } else { let routeCur: route_data = { name: menu.name, path: menu.url, meta: { title: menu.meta.title, idx: menu.meta.idx }, children: [], component: null } //方式1 动态组件 /* @vite-ignore */ 忽略vite警告 //vite语法不识别动态导入,报错:The above dynamic import cannot be analyzed by Vite. routeCur.component = () => import(/* @vite-ignore */'../views' + menu.url + '.vue'); //方式2 动态组件 // routeCur.component = defineAsyncComponent(() => import(/* @vite-ignore */'../views' + menu.url + '.vue')) return routeCur; } } // 检查是否存在于免登陆白名单 const inWhiteList = (toPath: any) => { const whiteList = ['/login'] let str = toPath.toLowerCase(); if (whiteList.indexOf(str) > -1) { return true; } return false; } export default router