动态路由(前端/后端 控制)
动态路由后台管理系统,大部分都会涉及到权限控制这一项需求,即:根据不同登录角色渲染不同页面功能现在主流有两种方式:前端控制逻辑简单,上手快后端控制相对安全,需要后期改动前端控制可以参考花裤衩的文章,手摸手,带你用vue撸后台 系列二(登录权限篇)核心:通过 token 获取用户的 role,根据 role 动态跟路由表 meta.role 进行匹配,形成可访问的路由再通过 router.addRo
动态路由
后台管理系统,大部分都会涉及到权限控制这一项需求,即:根据不同登录角色渲染不同页面功能
现在主流有两种方式:
-
前端控制
逻辑简单,上手快
-
后端控制
相对安全,需要后期改动
后端控制
后端路由时大部分后台管理项目的解决方案
核心:用户登录以后,后端根据该角色生成可访问的路由数据,前端根据这个路由数据转换成自己需要的路由结构
具体代码结构:
-
router 文件中,只放一些静态路由和公共路由
代码参考:https://github.com/PanJiaChen/vue-element-admin/blob/master/src/router/index.js
-
在 vuex 中写一个 state,把路由和获取到的角色进行匹配,控制菜单栏的显示隐藏
import { constantRoutes } from '@/router' import { getRoutes } from '@/api/menu' import Layout from '@/layout/index' // 遍历后台传来的路由字符串,转换为组件对象 function filterAsyncRoutes(asyncRouterMap) { return asyncRouterMap.filter(route => { if (route.component) { // Layout组件特殊处理 if (route.component === 'Layout') { route.component = Layout } else { route.component = loadView(route.component) } } if (route.children && route.children.length) { route.children = filterAsyncRoutes(route.children) } return true }) } function loadView(view) { // 注意:webpack4动态import不支持变量方式,如下写法是不行的 // return () => import(`@/views/${view}`) return resolve => require([`@/views/${view}`], resolve) } const permission = { state: { routes: [], addRoutes: [], }, mutations: { SET_ROUTES: (state, routes) => { state.addRoutes = routes state.routes = constantRoutes.concat(routes) }, }, actions: { GenerateRoutes({ commit }) { const Id = sessionStorage.getItem('SESSION_KEY') return new Promise(resolve => { getRoutes(Id).then(res => { const accessedRoutes = filterAsyncRoutes(res.data) accessedRoutes.push({ path: '*', redirect: '/404', hidden: true }) commit('SET_ROUTES', accessedRoutes) resolve(accessedRoutes) }) }) }, }, }
-
给后端整理一份前端需要的 router 数据结构
一般必须有的参数:id、path、name、title、children
path: # 路由地址 name: # 路由名称 id: # id component: # 组件路径 meta->title: # 菜单名称(和path同级就可以) meta->icon: # 菜单图标(和path同级就可以) meta->type: # 菜单类型,用于区分模块、目录、菜单、按钮 meta->hidden: # 是否全局隐藏此菜单 children: # 子集集合
如果后端传的不是 children,是 parentId 那种类型,则需要写一个转换方法
方法可以参考这篇文章:Vue 封装无限层级树形菜单组件(后台传的是扁平数组)
-
在导航守卫中,使用
router.beforeEach
进行拦截,可以动态添加可访问的路由表(使用 addRoutes 添加)import NProgress from 'nprogress' import 'nprogress/nprogress.css' NProgress.configure({ showSpinner: false }) const whiteList = ['/login', '/auth-redirect', '/bind', '/register'] router.beforeEach((to, from, next) => { NProgress.start() // 判断是否有token if (store.getters.token) { if (to.path === '/login') { next({ path: '/' }) } else { // 判断当前用户是否已拉取完user_info信息 if (store.getters.roles.length === 0) { // 获取info信息 store.dispatch('GetInfo').then(res => { const roles = res.roles store .dispatch('GenerateRoutes', { roles }) .then(accessRoutes => { // 动态添加可访问路由表 router.addRoutes(accessRoutes) // hack方法 确保addRoutes已完成 next({ ...to, replace: true }) }) .catch(err => { console.log(err) }) }) } else { // 当有用户权限的时候,说明可访问路由表已生成 next() } } } else { if (whiteList.includes(to.path)) { // 在免登录白名单,直接进入 next() } else { // 否则全部重定向到登录页 next('/login') } } })
-
从 router 中取出可用的路由对象,来进行侧边栏的渲染
也可以参考这篇文章:后端控制路由
前端控制
可以参考花裤衩的文章,手摸手,带你用vue撸后台 系列二(登录权限篇)
核心:通过 token 获取用户的 role,根据 role 动态跟路由表 meta.role
进行匹配,形成可访问的路由再通过 router.addRotes
动态挂载路由
具体代码结构:
- 可以参考:动态路由前端控制还是后端控制?(附代码)
-
把动态路由和静态路由分别写在 router 文件中(
asyncRoutes/constantRoutes
)。在动态路由的 meta 元信息中添加 roles 权限代码参考:https://github.com/PanJiaChen/vue-element-admin/blob/master/src/router/index.js
-
在 vuex 中写一个 state,把路由和获取到的角色进行匹配,控制菜单栏的显示隐藏
代码参考:https://github.com/PanJiaChen/vue-element-admin/blob/master/src/store/modules/permission.js
-
在导航守卫中,使用
router.beforeEach
进行拦截,可以动态添加可访问的路由表(使用 addRoutes 添加)https://github.com/PanJiaChen/vue-element-admin/blob/master/src/permission.js
-
从 router 中取出可用的路由对象,来进行侧边栏的渲染
https://github.com/PanJiaChen/vue-element-admin/blob/master/src/layout/components/Sidebar/index.vue
更多推荐
所有评论(0)