动态路由
目的: 根据服务器传回来的数据动态的注册路由信息,登录用户的角色不同生成的菜单不同
使用插件做动态路由的好处: 路由页面增加或者减少时,只需要增加或减少相关的路由文件,不需要再修改代码
- 服务器返回的信息格式中需要有路由信息
"route": "/home/user",
,说明该角色有访问"/home/user"
路由的权限
// 角色权限
{
{
"id": 1,
"route": "/home/user",
"name": "用户管理",
},
{
"id": 2,
"route": "/home/department",
"name": "部门管理",
},
{
"id": 3,
"route": "/home/menu",
"name": "菜单管理",
},
{
"id": 4,
"route": "/home/role",
"name": "角色管理",
}
}
1. 全局安装coderwhy插件
pnpm i coderwhy -g
// 检查是否安装成功
coderwhy --version
// 1.2.2
2. coderwhy插件使用
- 示例
coderwhy add3page_setup index -d src/views/main/system/department
- 执行命令后会自动生成两个文件
-
在命令中指定的目录
src/views/main/system/department
生成.vue
文件
-
同时自动在
router文件夹
下生成相同路径、相同文件名的.ts
文件
-
- 组件:index.vue
<template>
<div class="index">
<h2>index</h2>
</div>
</template>
<script setup lang="ts" name="index"></script>
<style scoped>
.index {
}
</style>
- 路由文件:index.ts
const index = () => import('@/views/main/system/department/index.vue')
export default {
path: '/main/system/department',
name: 'index', // 这里需要修改为department
component: index,
children: []
}
- 使用插件将所有的路由文件和组件文件全部创建好
3. 把所有文件中的路由导出,组成一个数组
import type { RouteRecordRaw } from 'vue-router'
function getAllMainRoutes(): RouteRecordRaw[] {
// 1. 获取所有路由文件,每一个文件对应一个路由,一个文件是一个对象
const modules: Record<string, any> = import.meta.glob('@/router/main/**/*.ts', {
eager: true,
import: 'default'
})
// 2. 把文件中中的路由信息放入数组中
let allRoutes: RouteRecordRaw[] = []
allRoutes = Object.values(modules)
return allRoutes
}
allRoutes
:是所有路由的集合,它是从文件生成的,以后只需要在相应的位置添加vue组件对应的路由文件,这个方法就会自动生成路由的集合
5. 动态生成路由
将 allRoutes
与服务器返回的 角色的路由信息 进行比对,就能生成该角色对应的路由表
// roleMenu:服务器返回的角色权限
function mainAddChildrenRoutes(roleMenu: []): RouteRecordRaw[] {
const routes: RouteRecordRaw[] = []
const roleRoutes = getAllMainRoutes() // 所有的路由
// 3. 遍历菜单信息,把菜单信息中的url与路由信息中的path进行匹配
for (const menu of roleMenu) {
const route = roleRoutes.find((item) => item.path === menu.route)
if (route) routes.push(route)
}
return routes // 返回结果是动态路由,下一步只需要将路由加载到路由器中
}
6. 使用动态路由后刷新白屏
- 刷新页面会导致加载到路由器的动态路由丢失,需要在刷新的同时将动态路由重新加载到路由器
- 从登录页面进入时加载一次动态路由(登录的请求完成后,页面跳转之前)
- 在pinia加载后,route加载前重新加载一次动态路由到路由器
- pinia改写
import { createPinia } from 'pinia'
import type { App } from 'vue'
import { useLoginStore } from '@/stores/login'
function setupPinia(app: App<Element>) {
const pinia = createPinia()
app.use(pinia) // 加载pinia
// 初始化角色菜单,加载路由到路由器
const loginStore = useLoginStore()
loginStore.setRoleMenu()
}
export default setupPinia
// main.js
setupPinia(app)