Vue动态路由生成多级菜单函数封装

动态路由生成

后端请求到的接口里面的菜单根据pid产生多级联动;以下的代码将会自动生成vue里面的路由结构

调用
  • Tree(菜单数据)
定制化修改函数
  • generator()
  • currentRouter 这个里面可以定制化修改所需要的path、meta、component等
代码如下:
/**
 * 
 * @param {*} option 
 * @returns menus菜单数据   数组
 */
export function Three(option) {
    let resNav = option //最初的原始菜单
    let menuNav = [] //顶级菜单
    generatorDynamicRouter(option)

    /**
     * 动态生成菜单
     * @param data 原始的路由数据
     * @returns {Promise<Router>}
     */
    function generatorDynamicRouter(data) {
        return new Promise((resolve, reject) => {
            const childrenNav = [] //子菜单
            //     后端数据, 根级树数组,  根级 PID
            listToTree(resNav, childrenNav, 0)
            resolve()
        }).catch(err => {
            // reject('加载菜单失败')
            return Promise.reject(err)
        })
    }

    /**
     * 数组转树形结构
     * @param list 源数组
     * @param tree 树
     * @param parentId 父ID
     * 递归调用生成树状结构
     */
    function listToTree(list, tree, parentId) {

        list.map(item => {
            // 判断是否为父级菜单
            if (item.pid == 0) {
                menuNav = item
            }
            // eslint-disable-next-line eqeqeq
            if (item.pid == parentId) {
                const child = {
                    ...item,
                    key: item.key || item.name,
                    children: []
                }
                // 迭代 list, 找到当前菜单相符合的所有子菜单
                listToTree(list, child.children, item.id)
                // 删掉不存在 children 值的属性
                if (child.children.length <= 0) {
                    delete child.children
                }
                // 加入到树中
                tree.push(child)
            }
        })

        menus = generator(tree, menuNav)
    }
    /**
     * 格式化树形结构数据 生成 vue-router 层级路由表
     *
     * @param routerMap 源数据
     * @param parent    树结构
     * @returns {*}
     * 
     * 数据拼接  
     */
    function generator(routerMap, parent) {
        // 最后一层的拼接操作
        // 子集数组   父级格式化好的数据
        //   console.log(routerMap,"子集");
        //   console.log(parent, '父级')
        return routerMap.map(item => {
            // eslint-disable-next-line no-unused-vars
            const { title, show, hideChildren, hiddenHeaderContent, target, icon, link } = item.meta || {}
            const currentRouter = {
                // 如果路由设置了 path,则作为默认 path,否则 路由地址 动态拼接生成如 /dashboard/workplace
                path: item.path || `${parent && parent.path || ''}/${item.key}`,
                // 路由名称,建议唯一
                name: item.name || item.key || '',
                // 该路由对应页面的 组件 :方案1
                // component: constantRouterComponents[item.component || item.key],
                // 该路由对应页面的 组件 :方案2 (动态加载)
                component: `() => import(@/views/${item.component})`,
                // meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
                meta: {
                    title: title,
                    icon: icon || undefined,
                    // hiddenHeaderContent: hiddenHeaderContent,
                    target: target,
                    link: link
                }
            }
            // 是否设置了隐藏菜单
            if (show === false) {
                currentRouter.hidden = true
            }
            // 是否设置了隐藏子菜单
            if (hideChildren) {
                currentRouter.hideChildrenInMenu = true
            }
            // 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠
            if (!currentRouter.path.startsWith('http')) {
                currentRouter.path = currentRouter.path.replace('//', '/')
            }
            // 重定向
            item.redirect && (currentRouter.redirect = item.redirect)
            // 是否有子菜单,并递归处理
            if (item.children && item.children.length > 0) {
                // Recursion
                currentRouter.children = generator(item.children, currentRouter)

            }

            return currentRouter

        })

    }


    return menus
}

总结:可以根据后端生成的数据来进行动态路由的设置,更大的限制了权限。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值