Vue-element-admin实现动态路由
Vue-element-admin实现动态路由
一 克隆与安装Vue
此步骤省略,因为都是对Vue-element-admin进行二次开发
二 关于Vue-element-admin内部结构分析
1 静态路由
vue-element-admin是一款开源免费前端后台系统管理框架,clone即用,非常方便,对应它存在的两种路由设计,一种是静态路由,一种是动态路由。
这是vue为了提供的静态路由中一些常用页面,比如根目录,登录,404等,如果还需要添加左边栏菜单,可以模仿静态路由的设计里面,还有权限的设计。
2 动态路由
(1)修改/src/store/modules/permission.js 文件
import { asyncRoutes, constantRoutes } from '@/router' import { getAuthMenu } from '@/api/user' import Layout from '@/layout' /** * Use meta.role to determine if the current user has permission * @param roles * @param route */ function hasPermission(roles, route) { if (route.meta && route.meta.roles) { return roles.some(role => route.meta.roles.includes(role)) } else { return true } } /** * 后台查询的菜单数据拼装成路由格式的数据 * @param routes (resolve: any) => require([`@/views/${view}.vue`], resolve) */ export function generaMenu(routes, data) { data.forEach(item => { // alert(JSON.stringify(item)) const menu = { path: item.path === '#' ? item.id + '_key' : item.path, // component: item.component === '#' ? Layout : () => import(`@/views${item.component}`), component: item.component === '#' ? Layout : (resolve) => require([`@/views${item.component}`], resolve), hidden: item.hidden, redirect: item.redirect, children: [], name: item.name, meta: item.meta // meta: { title: item.name, id: item.id, roles: ['admin'] } } if (item.children) { generaMenu(menu.children, item.children) } routes.push(menu) }) } /** * Filter asynchronous routing tables by recursion * @param routes asyncRoutes * @param roles */ export function filterAsyncRoutes(routes, roles) { const res = [] routes.forEach(route => { const tmp = { ...route } if (hasPermission(roles, tmp)) { if (tmp.children) { tmp.children = filterAsyncRoutes(tmp.children, roles) } res.push(tmp) } }) return res } const state = { routes: [], addRoutes: [] } const mutations = { SET_ROUTES: (state, routes) => { state.addRoutes = routes state.routes = constantRoutes.concat(routes) } } const actions = { generateRoutes({ commit }, roles) { return new Promise(resolve => { const loadMenuData = [] // 先查询后台并返回左侧菜单数据并把数据添加到路由 getAuthMenu(state.token).then(response => { let data = response if (response.code !== 20000) { alert(JSON.stringify('菜单数据加载异常')) // throw new Error('菜单数据加载异常') } else { data = response.data Object.assign(loadMenuData, data) const tempAsyncRoutes = Object.assign([], asyncRoutes) // tempAsyncRoutes = asyncRoutes generaMenu(tempAsyncRoutes, loadMenuData) let accessedRoutes if (roles.includes('admin')) { // alert(JSON.stringify(asyncRoutes)) accessedRoutes = tempAsyncRoutes || [] } else { accessedRoutes = filterAsyncRoutes(tempAsyncRoutes, roles) } commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) } // generaMenu(asyncRoutes, data) }).catch(error => { console.log(error) }) }) } } export default { namespaced: true, state, mutations, actions }
对照一下原版就可以发现更改的部分,这里面一般在编译的时候会出现rang of null的错误,这是因为你的babel-eslint版本过高的原因,因为老外改过打包的底层逻辑。所以我门一劳永逸,直接降低版本:
npm i babel-eslint@7.2.3
* 修改 /src/router/index.js *
export const asyncRoutes = [ { path: '*', redirect: '/404', hidden: true } ]
动态路由只留下这个就行了。不过你之前写过的静态路径也要注释掉。
(3) 添加动态路由的请求方法 /src/api/user.js
export function getAuthMenu() { return request({ url: '/configinfo/getAuthMenu ', method: 'post' }) }
这里面你需要什么参数可以携带进去,比如权限什么都可能。
(4) 重点就是后端返回的JSON串了
{"code":20000,"data":[{"id":1,"hidden":true,"name":"GSMSystem","path":"/GSMSystem","pid":0,"url":"/GSMSystem","alwaysShow":true,"component":"#","meta":{"icon":"icon","status":true,"title":"GSM后台"},"children":[{"alwaysShow":true,"component":"/GSMSystem/paramOption/index","hidden":false,"id":11,"meta":{"icon":"paramOption","status":true,"title":"参数配置"},"name":"paramOption","path":"GSMSystem/paramOption","pid":30,"url":"GSMSystem/paramOption"},{"alwaysShow":true,"component":"/GSMSystem/logInformation/index","hidden":false,"id":11,"meta":{"icon":"logInformation","status":true,"title":"日志显示"},"name":"logInformation","path":"GSMSystem/logInformation","pid":30,"url":"GSMSystem/logInformation"},{"alwaysShow":true,"component":"/GSMSystem/logInformationQuery/index","hidden":false,"id":11,"meta":{"icon":"logInformationQuery","status":true,"title":"日志查询"},"name":"logInformationQuery","path":"GSMSystem/logInformationQuery","pid":30,"url":"GSMSystem/logInformationQuery"},{"alwaysShow":true,"component":"/GSMSystem/scanRateStatus/index","hidden":false,"id":11,"meta":{"icon":"scanRateStatus","status":true,"title":"扫描状态"},"name":"scanRateStatus","path":"GSMSystem/scanRateStatus","pid":30,"url":"GSMSystem/scanRateStatus"},{"alwaysShow":true,"component":"/GSMSystem/heartLog/index","hidden":false,"id":11,"meta":{"icon":"heartLog","status":true,"title":"GSM心跳显示"},"name":"heartLog","path":"GSMSystem/heartLog","pid":30,"url":"GSMSystem/heartLog"},{"alwaysShow":true,"component":"/GSMSystem/updateData/index","hidden":false,"id":11,"meta":{"icon":"updateData","status":true,"title":"更新程序"},"name":"updateData","path":"GSMSystem/updateData","pid":30,"url":"GSMSystem/updateData"}]},{"id":2,"hidden":true,"name":"hbcdmadisplay","path":"/hbcdmadisplay","pid":1,"url":"/hbcdmadisplay","alwaysShow":true,"component":"#","meta":{"icon":"icon","status":true,"title":"CDMA后台"},"children":[{"alwaysShow":true,"component":"/hbcdmadisplay/index","hidden":false,"id":11,"meta":{"icon":"hbcdmadisplay","status":true,"title":"hbcdmadisplay"},"name":"hbcdmadisplay","path":"/hbcdmadisplay","pid":30,"url":"/hbcdmadisplay"}]},{"id":3,"hidden":false,"name":"interception","path":"/interception","pid":2,"url":"/interception","alwaysShow":true,"component":"#","meta":{"icon":"icon","status":true,"title":"截取任务"},"children":[{"alwaysShow":true,"component":"/interception/taskmanagement/index","hidden":false,"id":11,"meta":{"icon":"taskmanagement","status":true,"title":"任务管理"},"name":"taskmanagement","path":"interception/taskmanagement","pid":30,"url":"interception/taskmanagement"}]}]}
GsomFormat插件可以直接转译成类即可使用
//这是设计好的类,可以直接使用 import java.util.List; public class RouterMeunInfo { public int id; public boolean hidden; public String name; public String path; public int pid; public String url; public boolean alwaysShow; public String component; //涉及meta内部集合 public Meta meta; //设计chilren public List<Children> children; public static class Meta{ public String icon; public boolean status; public String title; } public static class Children{ public boolean alwaysShow; public String component; public boolean hidden; public int id; public Meta meta; public String name; public String path; public int pid; public String url; } }
至于案列,转译一下json就可以看出来里面的逻辑了。