权限菜单的业务
客户端角色分为超级管理员,普通管理员,普通用户等不同等级,服务端动态配置各等级可访问的前端页面,前端根据服务端下发的角色权限来动态渲染路由和菜单(后台管理平台菜单)。
listTree
这里后端的数据并不会返回给你tree数据,而是扁平的需要前端根据不同的业务场景自己手动进行处理。让数据结构成树状的。
数据处理:pid为0的代表就是最外层的数据,而它对应的id就是为了匹配子级pid。
let menu = [
{
"id": 2,
"pid": 0,
"path": "course",
"link": "/course/operate",
"name": "Course",
"title": "课程管理"
},
{
"id": 3,
"name": "CourseOperation",
"path": "operate",
"link": "/course/CourseOperation",
"pid": 2,
"title": "课程操作"
},
{
"id": 4,
"pame": "CourseInfoData",
"path": "info data",
"link": "/course/operate/info_dat",
"pid": 3,
"title": "课程数据"
},
{
"id": 5,
"name": "CourseAdd",
"path": "add",
"link": "/course/add",
"pid": 2,
"title": "增加课程"
},
{
"id": 6,
"pid": 0,
"path": "/student",
"name": "Student",
"title": "学生管理"
},
{
"id": 7,
"name": "Studentoperate",
"path": "operate",
"link": "/student/operate",
"pid": 6,
"title": "学生操作"
},
{
"id": 8,
"name": "StudentAdd",
"path": "add",
"link": "/student/add",
"pid": 6,
"title": "增加学生"
}
]
// list toTree resulted
/*
[
{
"id": 2,
"pid": 0,
"path": "course",
"link": "/course/operate",
"name": "Course",
"title": "课程管理",
"children": [
{
"id": 3,
"name": "CourseOperation",
"path": "operate",
"link": "/course/CourseOperation",
"pid": 2,
"title": "课程操作",
"children": [
{
"id": 4,
"pame": "CourseInfoData",
"path": "info data",
"link": "/course/operate/info_dat",
"pid": 3,
"title": "课程数据"
}
]
},
{
"id": 5,
"name": "CourseAdd",
"path": "add",
"link": "/course/add",
"pid": 2,
"title": "增加课程"
}
]
},
{
"id": 6,
"pid": 0,
"path": "/student",
"name": "Student",
"title": "学生管理",
"children": [
{
"id": 7,
"name": "Studentoperate",
"path": "operate",
"link": "/student/operate",
"pid": 6,
"title": "学生操作"
},
{
"id": 8,
"name": "StudentAdd",
"path": "add",
"link": "/student/add",
"pid": 6,
"title": "增加学生"
}
]
}
]
*/
// 代码处理逻辑主要利用递归
function toTree(menus) {
// 第一步是将第一层父级的数据过滤出来 和子级的数据过滤出来
let prents = menus.filter(item => item.pid == 0)
let chids = menus.filter(item => item.pid != 0)
// 调用核心方法
listToTree(prents, chids)
//最后返回处理后的数据
return prents
function listToTree(parPrents, parChids) {
//循环父级数据,父级内部循环子级数据
parPrents.map(prent => {
parChids.map((chid, index) => {
// 如果父级的id 等于子级的 pid 的话说明父亲找到儿子了。
if (prent.id == chid.pid) {
// 这里是拷贝了一份子级的数据
let chidClone = JSON.parse(JSON.stringify(chids))
// 开始递递归,将当前匹配到的子级,再次传入查询子级的子级
listToTree([chid], chidClone)
//这里是判断有没有 children 有的话将当前的子级添加到父级
if (prent.children) {
prent.children.push(chid)
} else {
// 没有 children 添加一个 children
prent.children = [chid]
}
}
})
})
}
}
console.log(toTree(menus))
import.meta.glob 函数从文件系统导入多个模块
router.addRoute('home', route) 添加每一个路由对象(addRoute 只能追加对象)
console.log(444, router.getRoutes(), to) 可以通过getRoutes 查看添加对象
let modules = import.meta.glob('../views/**/*.vue') 获取views文件下的所有(2个星号代表文件夹 1个星号代表文件)文件夹中的.vue 文件
function generateRouter(routeTree: Iroute[]) {
if(typeof routeTree == 'undefined') return
let newRoute = routeTree.map(route => {
/*
Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块:
const modules = import.meta.glob('./dir/*.js')
以上将会被转译为下面的样子:
vite 生成的代码
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js'),
}
获取views文件下的所有.vue 文件
let modules = import.meta.glob('../views/*.vue')
获取views文件下的所有(2个星号代表文件夹 1个星号代表文件)文件夹中的.vue 文件
let modules = import.meta.glob('../views/2个星号/*.vue')
*/
// 获取views文件下的所有.vue 文件
let modules = import.meta.glob('../views/*.vue')
console.log(3455435, modules)
let _route: RouteRecordRaw = {
path: route.link ? route.link : route.path,
name: route.name,
component: modules[`../views/${route.name}.vue`],
children: []
}
if (route.children) {
_route.children = generateRouter(route.children)
}
return _route
})
return newRoute
}
export function routerBeforeEach(router: Router, store: any) {
router.beforeEach(async (to, form, next) => {
// 解决刷新动态路由丢失的问题 判断没有menu 重新添加有了就 next()执行当前页面
if (store.state.menu.length == 0) {
await store.dispatch('getMenuList', store.state.auth)
const routerToTree = generateRouter(store.state.menu)
// addRoute 只能追加对象
// 添加到 home 的children下
routerToTree.forEach(route => {
router.addRoute('home', route)
})
// 可以通过getRoutes 查看添加对象
console.log(444, router.getRoutes(), to)
next({path: to.path})
} else {
next()
}
})
}
在app.js 文件引入
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import store from "./store";
// @ts-ignore
import router from './router'
import {routerBeforeEach} from '@/router/route'
routerBeforeEach(router,store)
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App).use(store).use(router).use(ElementPlus).mount('#app')
文章评论