Vue 实现动态生成路由(动态生成菜单,根据菜单动态生成路由)

https://blog.csdn.net/tly599167/article/details/107378249/

一、动态菜单显示

  1. 后端返回的菜单数据处理
    后端返回的菜单数据一般有两种,处理好的树状结构、或者未处理的列表数据(这种情况需要我们去转换成树状结构,可看我的另外一篇博客【js树形结构操作】)。

下面是后端返回的数据:
[
{
“id”: “1”,
“pid”: “0”,
“name”: “工作台”,
“url”: “/dashboard”,
“icon”: “el-icon-s-platform”,
“children”: []
},
{
“id”: “2”,
“pid”: “0”,
“name”: “教务管理”,
“icon”: “el-icon-s-opportunity”,
“children”: [
{
“id”: “21”,
“pid”: “2”,
“name”: “学员中心”,
“url”: “/educate/student”
},
{
“id”: “22”,
“pid”: “2”,
“name”: “班级管理”,
“url”: “/educate/class”
},
{
“id”: “23”,
“pid”: “2”,
“name”: “课程管理”,
“url”: “/educate/course”
},
{
“id”: “24”,
“pid”: “2”,
“name”: “课表管理”,
“url”: “/educate/table”
}
]
},
{
“id”: “3”,
“pid”: “0”,
“name”: “系统设置”,
“icon”: “el-icon-s-opportunity”,
“children”: [
{
“id”: “31”,
“pid”: “3”,
“name”: “基础信息”,
“url”: “/setting/base”
},
{
“id”: “32”,
“pid”: “3”,
“name”: “职员管理”,
“url”: “/setting/user”
},
{
“id”: “33”,
“pid”: “3”,
“name”: “岗位管理”,
“url”: “/setting/role”
}
]
},

]
拿到后端的数据后,使用Vuex管理这些菜单数据。

  1. 显示菜单列表
    在菜单组件中,使用Vuex的中的菜单数据回显:







{{group.name}}



{{menu.name}}




{{group.name}}




在这里插入图片描述
至此,通过后端返回的菜单数据动态生成菜单已完成。但是细心的小伙伴会发现,手动输入没有菜单的URL,仍然可以查看显示,这是不安全的,并且菜单栏无匹配项。

二、动态生成路由

  1. 把路由分类
    路由需要分成两类,静态路由和动态路由。静态路由是任何菜单权限下都能查看的界面路由;动态路由是根据菜单权限动态生成的路由集合。这里的动态路由与VueRouter的动态路由概念没有任何关系。
    比如:
    /** router.js */

/**

  • 静态路由
    /
    export const constantRouterMap = [
    {
    path: ‘/’,
    redirect: ‘/dashboard’
    },
    {
    path: ‘/login’,
    name: ‘Login’,
    component: () => import(’@/views/Login’)
    },
    {
    path: ‘/forgetPassword’,
    name: ‘ForgetPassword’,
    component: () => import(’@/views/ForgetPassword’)
    },
    {
    path: ‘/register’,
    name: ‘Register’,
    component: () => import(’@/views/Register’)
    },
    {
    path: '
    ’,
    name: ‘404’,
    component: () => import(’@/views/404’)
    }
    ]

/**

  • 需要动态添加的路由
    */
    export const asyncRouterMap = [
    {
    path: ‘/educate’,
    name: ‘Educate’,
    component: Layout,
    meta: {
    title: ‘教务管理’
    },
    children: [
    {
    path: ‘student’,
    name: ‘Student’,
    component: () => import(’_v/educate/student’),
    meta: {
    keepAlive: true,
    title: ‘学员中心-桃李云帮’
    }
    },
    {
    path: ‘studentEnroll’,
    name: ‘StudentEnroll’,
    component: () => import(’_v/educational/studentEnroll’),
    meta: {
    isLeaf: true,
    title: ‘学员报名-桃李云帮’
    }
    },
    {
    path: ‘class’,
    name: ‘Class’,
    component: () => import(’_v/educate/class’),
    meta: {
    // keepAlive: true,
    title: ‘班级管理-桃李云帮’
    }
    },
    {
    path: ‘timetable’,
    name: ‘Timetable’,
    component: () => import(’_v/educate/table’),
    meta: {
    // 不需要缓存
    title: ‘课表管理-桃李云帮’
    }
    },
    {
    path: ‘course’,
    name: ‘Course’,
    component: () => import(’_v/educate/course’),
    meta: {
    keepAlive: true,
    title: ‘课程管理-桃李云帮’
    }
    }
    ]
    },
    executiveRoute,

    ]

export default new Router({
mode: ‘hash’,
base: process.env.BASE_URL,
routes: constantRouterMap // 这里只返回静态路由
})

  1. 动态匹配路由
    使用VueRouter的router.addRoutes(routes: Array)方法,动态添加路由。
    注意:这里是通过URL匹配,你也可以根据其他方式匹配。 isLeaf表示不在菜单中的路由,应该根据权限来判断是否动态添加路由

/** store.js */
addUserMenus({ commit }, menus) {
commit(‘setMenuList’, menus)
// 扁平化菜单数据
const menuList = treeToList(menus.concat([]))
const addRoutes = []
let tempPath = ‘’
let tempList = []
// 这里只做了两层的路由处理
asyncRouterMap.forEach(item1 => {
tempPath = item1.path || ‘’
tempList = []
if (item1.children) {
item1.children.forEach(item2 => {
// TODO isLeaf是写死的,应该按照权限判断
if ((item2.meta && item2.meta.isLeaf) || menuList.find(o => o.url && path.join(tempPath, item2.path).toLowerCase() === o.url.toLowerCase())) {
tempList.push(item2)
}
})
}
if (tempList.length > 0) {
addRoutes.push(Object.assign({}, item1, {
children: tempList
}))
}
})
// 添加授权路由页面
Router.addRoutes(addRoutes)
}

treeToList方法

/**

  • 树 转 列表
  • 广度优先,先进先出
  • @param {Array} tree 树状数据
  • @param {String} childKey children的key
    */
    export function treeToList(tree, childKey = ‘children’) {
    let stack = tree.concat([])
    let data = []
    while (stack.length !== 0) {
    // 从stack中拿出来分析
    let shift = stack.shift() // stack.pop() 先进后出
    data.push(shift)
    let children = shift[childKey]
    if (children) {
    for (let i = 0; i < children.length; i++) {
    // 把数据放入stack中
    stack.push(children[i])
    }
    }
    }
    return data
    }
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值