vue3+vite处理listToTree权限菜单数据处理为树形数据以及动态import页面配置动态路由。

权限菜单的业务

客户端角色分为超级管理员,普通管理员,普通用户等不同等级,服务端动态配置各等级可访问的前端页面,前端根据服务端下发的角色权限来动态渲染路由和菜单(后台管理平台菜单)。

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')

猜你喜欢

转载自blog.csdn.net/qq_54753561/article/details/129495292
今日推荐