首页 > 编程知识 正文

vue动态路由及生成菜单教程,vue动态路由如何实现

时间:2023-05-04 16:12:48 阅读:272519 作者:2098

在后台管理系统中,常常会因为不同的权限,展现不同的菜单。但这仅仅是显示控制,而我们要做的是没有的菜单权限,直接输入URL也不可访问,真正的实现菜单权限控制。

一、动态菜单显示 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管理这些菜单数据。

2. 显示菜单列表

在菜单组件中,使用Vuex的中的菜单数据回显:

<!-- 菜单组件 --><el-menu class="sidebar-menu" router :default-active="$route.path" :collapse="!sidebar.opened" :collapse-transition="false" :show-timeout="200" unique-opened background-color="#272a36" text-color="#e7e7e7" active-text-color="#ff6600"> <el-scrollbar wrap-class="scrollbar-wrapper" style="height: 100%;"> <template v-for="group in menuList"> <el-submenu v-if="group.children && group.children.length > 0" :key="group.id" :index="group.id"> <template slot="title"> <i :class="group.icon"></i> <span slot="title">{{group.name}}</span> </template> <el-menu-item v-for="menu in group.children" :key="menu.id" :index="menu.url"> <i class="icon iconfont icon-pointer" style="vertical-align: baseline;"/> {{menu.name}} </el-menu-item> </el-submenu> <el-menu-item v-else :key="group.id" :index="group.url"> <i :class="group.icon"></i> <span slot="title">{{group.name}}</span> </el-menu-item> </template> </el-scrollbar></el-menu>

通过本页面的$route的URL进行菜单匹配,并不是全路径的URL。
至此,通过后端返回的菜单数据动态生成菜单已完成。但是细心的小伙伴会发现,手动输入没有菜单的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 // 这里只返回静态路由}) 2. 动态匹配路由

使用VueRouter的router.addRoutes(routes: Array<RouteConfig>)方法,动态添加路由。
注意:这里是通过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}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。