前端的路由从后台获取,包括权限;
大体步骤包括:路由拦截(钩子函数)---->后台获取路由数据 ----> 保存到本地或vuex中.
1 router.beforeEach((to, from, next) => { //拦截处一定要else{} 2 // 加载动态菜单和路由 3 if (to.path === '/') { 4 addDynamicMenuAndRoutes(to, from) 5 console.log(router.options.routes); 6 next() 7 } else { 8 if (store.state.menu.navTree) { 9 addDynamicMenuAndRoutes(to, from) 10 } 11 next() 12 } 13 })
一个Tip,钩子函数一定要记得else{},就这个小问题找了半天,各种排除。。。
我这里没有登录验证,所以通过path来判断是否加载动态路由;
下面的判断是由于vuex在F5刷新时会清空,所以通过里面是否有vuex里的某个状态来判断是否要再次加载路由;一般用登录的token判断;
下面是加载动态路由的关键函数:
1 /** 2 * 加载动态菜单和路由 3 */ 4 function addDynamicMenuAndRoutes(to, from) { 5 // 处理IFrame嵌套页面 6 handleIFrameUrl(to.path) 11 api.menu.findMenuTree() 12 .then(res => { 13 // 添加动态路由 14 console.log(res.data) 15 let dynamicRoutes = addDynamicRoutes(res.data) 16 // 处理静态组件绑定路由 17 handleStaticComponent(router, dynamicRoutes) 18 router.addRoutes(router.options.routes) 19 console.log(router.options.routes) 20 // 保存加载状态 21 store.commit('menuRouteLoaded', true) 22 // 保存菜单树 23 store.commit('setNavTree', res.data) 24 }).then(res => { 25 // api.user.findPermissions({ 'name': userName }).then(res => { 26 // // 保存用户权限标识集合 27 // store.commit('setPerms', res.data) 28 // }) 29 }) 30 .catch(function(res) {}) 31 }
添加动态路由:
1 /** 2 * 添加动态(菜单)路由 3 * @param {*} menuList 菜单列表 4 * @param {*} routes 递归创建的动态(菜单)路由 5 */ 6 function addDynamicRoutes(menuList = [], routes = []) { 7 var temp = [] 12 for (var i = 0; i < menuList.length; i++) { 13 if (menuList[i].children && menuList[i].children.length >= 1) { 14 temp = temp.concat(menuList[i].children) 15 } else if (menuList[i].url && /\S/.test(menuList[i].url)) { 16 //menuList[i].url = menuList[i].url.replace(/^\//, '') 17 menuList[i].url = menuList[i].url.substring(1); 18 try { 19 // 根据菜单URL动态加载vue组件,这里要求vue组件须按照url路径存储 20 // 如url="sys/user",则组件路径应是"@/views/sys/user.vue",否则组件加载不到 21 let array = menuList[i].url.split('/') 22 let url = '' 23 for (let i = 0; i < array.length; i++) { 24 url += array[i].substring(0, 1).toUpperCase() + array[i].substring(1) + '/' 25 } 26 url = url.substring(0, url.length - 1) 27 var route = { 28 path: menuList[i].url, 29 component: resolve => require([`@/views/${url}`], resolve), 30 name: menuList[i].name, 31 meta: { 32 icon: menuList[i].icon, 33 index: menuList[i].id 34 } 35 } 36 } catch (e) {} 37 // } 38 routes.push(route) 39 } 40 } 41 if (temp.length >= 1) { 42 addDynamicRoutes(temp, routes) 43 } else { 44 // console.log('动态路由加载...') 45 // console.log('动态路由加载完成.') 46 } 47 return routes 48 }
模拟后台的路由数据:
1 "data": [{ 2 "id": 1, 3 "createBy": null, 4 "createTime": null, 5 "lastUpdateBy": null, 6 "lastUpdateTime": null, 7 "parentId": 0, 8 "name": "系统配置", 9 "url": null, 10 "perms": null, 11 "type": 0, 12 "icon": "el-icon-setting", 13 "orderNum": 0, 14 "delFlag": 0, 15 "parentName": null, 16 "level": 0, 17 "children": [{ 18 "id": 2, 19 "createBy": null, 20 "createTime": null, 21 "lastUpdateBy": null, 22 "lastUpdateTime": null, 23 "parentId": 1, 24 "name": "角色配置", 25 "url": "/sys/user", 26 "perms": null, 27 "type": 1, 28 "icon": "el-icon-service", 29 "orderNum": 1, 30 "delFlag": 0, 31 "parentName": "系统配置", 32 "level": 1, 33 "children": [] 34 }, { 35 "id": 3, 36 "createBy": null, 37 "createTime": null, 38 "lastUpdateBy": null, 39 "lastUpdateTime": null, 40 "parentId": 1, 41 "name": "业务配置", 42 "url": "/sys/dept", 43 "perms": null, 44 "type": 1, 45 "icon": "el-icon-news", 46 "orderNum": 2, 47 "delFlag": 0, 48 "parentName": "系统配置", 49 "level": 1, 50 "children": [] 51 }, { 52 "id": 4, 53 "createBy": null, 54 "createTime": null, 55 "lastUpdateBy": null, 56 "lastUpdateTime": null, 57 "parentId": 1, 58 "name": "权限配置", 59 "url": "/sys/role", 60 "perms": null, 61 "type": 1, 62 "icon": "el-icon-view", 63 "orderNum": 4, 64 "delFlag": 0, 65 "parentName": "系统配置", 66 "level": 1, 67 "children": [] 68 }, { 69 "id": 5, 70 "createBy": null, 71 "createTime": null, 72 "lastUpdateBy": null, 73 "lastUpdateTime": null, 74 "parentId": 1, 75 "name": "流程控制", 76 "url": "/sys/menu", 77 "perms": null, 78 "type": 1, 79 "icon": "el-icon-menu", 80 "orderNum": 5, 81 "delFlag": 0, 82 "parentName": "系统配置", 83 "level": 1, 84 "children": [] 85 }, 86 { 87 "id": 7, 88 "createBy": null, 89 "createTime": null, 90 "lastUpdateBy": null, 91 "lastUpdateTime": null, 92 "parentId": 1, 93 "name": "大数据", 94 "url": "/sys/dict", 95 "perms": null, 96 "type": 1, 97 "icon": "el-icon-edit-outline", 98 "orderNum": 7, 99 "delFlag": 0, 100 "parentName": "系统配置", 101 "level": 1, 102 "children": [] 103 }, 104 { 105 "id": 8, 106 "createBy": null, 107 "createTime": null, 108 "lastUpdateBy": null, 109 "lastUpdateTime": null, 110 "lastUpdateTime": "2018-09-23T11:32:28.000+0000", 111 "parentId": 1, 112 "name": "数据过滤", 113 "url": "/sys/log", 114 "perms": "sys:log:view", 115 "type": 1, 116 "icon": "el-icon-info", 117 "orderNum": 8, 118 "delFlag": 0, 119 "parentName": "系统配置", 120 "level": 1, 121 "children": [] 122 }, { 123 "id": 9, 124 "createBy": null, 125 "createTime": null, 126 "lastUpdateBy": "admin", 127 "lastUpdateTime": "2018-09-23T11:32:28.000+0000", 128 "parentId": 1, 129 "name": "系统维护", 130 "url": "/sys/dispose", 131 "perms": "sys:dispose:view", 132 "type": 1, 133 "icon": "el-icon-info", 134 "orderNum": 9, 135 "delFlag": 0, 136 "parentName": "系统配置", 137 "level": 1, 138 "children": [] 139 } 140 ] 141 } 142 ]
本文主要参考 朝雨忆轻尘,感谢大佬的详细介绍。
另附出处: https://www.cnblogs.com/xifengxiaoma/