前言
动态路由权限控制这块主要是几种,前端控制/后端控制/登录与菜单页分离等。本篇主要是分享下对路由在前端控制,这里使用了vue-element-admin的方法
使用
- 前端使用 vue+element-ui
- 后端使用 nodejs+koa
demo 效果
步骤
- 先定义好常规路由与动态路由列表
- 需要在 vuex 里维护权限,根据不同角色来分配路由
- 在 router.beforeEach 里来动态添加路由表
- 页面通过获得的路由来进行渲染
注意
- 退出前需要有重置路由这一操作,否则在用户不刷新的情况下,先登录管理员,再登录普通用户时,普通用户页面也有了管理员权限的页面。
- 在使用 next(…route, replace: true)时会产生一个报错,在 router 的 index.js 里加一段代码就好了(见完整源码)
关键源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| router.beforeEach(async (to, from, next) => { if (getToken()) { const hasRoles = store.getters.roles && store.getters.roles.length > 0; if (hasRoles) { next(); } else { try { const { roles } = await store.dispatch('user/getInfo'); const accessedRoutes = await store.dispatch( 'permission/generateRoutes', roles ); router.addRoutes(accessedRoutes); next({ ...to, replace: true }); } catch (err) { await store.dispatch('user/resetToken'); Message.error(err || 'Has Error'); next('/login'); } } } else { if (to.path === '/login') { next(); } else { next('/login'); } } });
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import { asyncRoutes, constantRoutes } from '../../router';
function hasPermisson(roles, route) { if (route.meta && route.meta.roles) { return roles.some((role) => route.meta.roles.includes(role)); } else { return true; } }
export function filterAsyncRoutes(routes, roles) { const res = []; routes.forEach((route) => { const tmp = { ...route }; if (hasPermisson(roles, tmp)) { if (tmp.children) { tmp.children = filterAsyncRoutes(tmp.children, roles); } res.push(tmp); } }); return res; } export default { namespaced: true, state: { routes: [], addRoutes: [], }, mutations: { SET_ROUTES: (state, routes) => { (state.addRoutes = routes), (state.routes = constantRoutes.concat(routes)); }, }, actions: { generateRoutes({ commit }, roles) { return new Promise((resolve) => { let accessedRoutes; if (roles.includes('ADMIN_USER')) { accessedRoutes = asyncRoutes || []; } else { accessedRoutes = filterAsyncRoutes(asyncRoutes, roles); } commit('SET_ROUTES', accessedRoutes); resolve(accessedRoutes); }); }, }, };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <-- home.vue --> <el-menu default-active="2" class="el-menu-vertical-demo" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" > <sidebarItem v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" ></sidebarItem> </el-menu>
|
完整源码
vue-permission-demo
参考链接