当前位置: 首页 > news >正文

vue-admin-template极简的 vue admin 管理后台的动态路由实现方法

项目源码地址:GitHub - PanJiaChen/vue-admin-template: a vue2.0 minimal admin template

注意:项目中的路由均写在 src\router\index.js 中,其中默认包含 constantRoutes 数组,这是固定路由,无论用户是什么角色,都需要显示这些路由内容(即导航栏)。

export const constantRoutes = [...
]

为了根据权限来动态的生成路由,我们需要添加 asyncRoutes 数组,这里面的内容将根据用户角色权限动态生成路由内容(即导航栏)。

export const asyncRoutes = [...
]

实现方法:

① 在 src\store\modules\permission.js 中,通过分析 asyncRoutes 里面的角色权限和当前用户所拥有的角色权限,生成用户可查看到的路由列表 permission_routes

② 在 src\layout\components\Sidebar\index.vue 中,遍历 permission_routes 显示菜单栏。

配置步骤

1、在 src\router\index.js 文件中

固定路由的写法,不需要任何权限,所有角色都可以访问

/*** 固定路由* 没有权限要求的基页* 所有角色都可以访问*/
export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/dashboard',component: () => import('@/views/dashboard/index'),hidden: true}/* {path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: '首页' }}]} */
]

动态路由的写法,需要我们添加的地方,根据权限显示的路由

/*** 异步路由* 需要根据用户角色动态加载的路由*/
export const asyncRoutes = [// 用户端 start{path: '/rescueActivity',redirect: '/rescueActivity',component: Layout,meta: { roles: ['user'] },children: [{path: '/rescueActivity',name: 'rescueActivity',component: () => import('@/views/user/rescue-activity'),meta: { title: '志愿救助活动' }}]},// 用户端 end// 管理员端 start{path: '/userManage',redirect: '/userManage',component: Layout,meta: { roles: ['admin'] },children: [{path: '/userManage',name: 'userManage',component: () => import('@/views/admin/user-manage'),meta: { title: '用户管理' }}]},// 管理员端 end// 404页一定要放在最后!!!{ path: '*', redirect: '/404', hidden: true }
]

通过修改 meta 属性中 roles

只有 admin 角色可以查看:meta: { roles: ['admin'] }

admin 和 user 都可以查看:meta: { roles: ['admin', 'user'] }

注意:{ path: '*', redirect: '/404', hidden: true } 必须放在最后面,并且只能放在 asyncRoutes 中,如果放在 constantRoutes 中的话,刷新页面会报 404 错误

2、在 src\store\modules\user.js 文件中

① 在 getDefaultState 里面的 avatar: '', 后面添加 roles: [] 值,如图:

roles: []

② 在 mutations 里面的 SET_AVATAR: (state, avatar) => { state.avatar = avatar }, 后面添加 SET_ROLES: (state, roles) => { state.roles = roles } 值,如图:

SET_ROLES: (state, roles) => {state.roles = roles
}

③ 在 getInfo 方法里面的 commit('SET_AVATAR', avatar) 后面添加 commit('SET_ROLES', roles) 值,如图:

const { name, avatar, roles } = data
commit('SET_ROLES', roles)

④ 在 logout、resetToken 方法里面的 commit('RESET_STATE') 后面添加 commit('SET_ROLES', []) 值,如图:

commit('SET_ROLES', [])

3、添加 src\store\modules\permission.js 文件

在 src\store\modules 目录下面没有 permission.js 文件,需要添加

permission.js
import { asyncRoutes, constantRoutes } from '@/router'/*** 使用 meta.role 来确定当前用户是否具有权限* @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 异步路由* @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) => {// 这个地方维护了两个状态一个是addRouters,一个是routesstate.addRoutes = routesstate.routes = constantRoutes.concat(routes)}
}const actions = {generateRoutes({ commit }, roles) {return new Promise(resolve => {const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)commit('SET_ROUTES', accessedRoutes)resolve(accessedRoutes)})}
}export default {namespaced: true,state,mutations,actions
}

4、在 src\store\getters.js 文件中

在 getters 里面的 name: state => state.user.name, 后面添加 roles: state => state.user.roles,  permission_routes: state => state.permission.routes 值,如图:

roles: state => state.user.roles,
permission_routes: state => state.permission.routes

5、将 src\permission.js 文件里面的内容全部替换掉

import router, { constantRoutes } from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'NProgress.configure({ showSpinner: false }) // NProgress Configurationconst whiteList = ['/login'] // no redirect whitelistrouter.beforeEach(async(to, from, next) => {// start progress barNProgress.start()// set page titledocument.title = getPageTitle(to.meta.title)// determine whether the user has logged inconst hasToken = getToken()if (hasToken) {if (to.path === '/login') {// if is logged in, redirect to the home pagenext({ path: '/' })NProgress.done()} else {const hasRoles = store.getters.roles && store.getters.roles.length > 0if (hasRoles) {next()} else {try {// get user info// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']const { roles } = await store.dispatch('user/getInfo')// generate accessible routes map based on rolesconst accessRoutes = await store.dispatch('permission/generateRoutes', roles)// dynamically add accessible routesrouter.options.routes = constantRoutes.concat(accessRoutes)router.addRoutes(accessRoutes)// hack method to ensure that addRoutes is complete// set the replace: true, so the navigation will not leave a history recordnext({ ...to, replace: true })} catch (error) {// remove token and go to login page to re-loginawait store.dispatch('user/resetToken')Message.error(error || 'Has Error')next(`/login?redirect=${to.path}`)NProgress.done()}}}} else {/* has no token*/if (whiteList.indexOf(to.path) !== -1) {// in the free login whitelist, go directlynext()} else {// other pages that do not have permission to access are redirected to the login page.next(`/login?redirect=${to.path}`)NProgress.done()}}
})router.afterEach(() => {// finish progress barNProgress.done()
})

6、在 src\layout\components\Sidebar\index.vue 文件中

将原来的 <sidebar-item ... /> 替换掉

<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />

在 ...mapGetters 里面的 'sidebar', 后面添加 'permission_routes' 值,如图:

'permission_routes'

7、在 src\store\index.js 文件中

import user from './modules/user' 下面添加 import permission from './modules/permission' 导入 permission 值;在 new Vuex.Store 里面的 user, 后面添加 permission 值,如图:

import permission from './modules/permission'
permission

相关文章:

  • 002_avoid_for_loop_in_Matlab避免使用for循环
  • Session、Cookie 和 Token的保存
  • 【蓝桥杯选拔赛真题72】python输出整数 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析
  • 软件测试教程 自动化测试之Junit框架
  • 网络安全进入AI赋能时代
  • 记录C++中,子类同名属性并不能完全覆盖父类属性的问题
  • Linux编程3.8 进程-守护进程
  • nodejs中使用@maxmind/geoip2-node 查询地理位置信息
  • MySQL的进阶使用方法
  • 3D开发工具HOOPS如何助力3D项目实现扩展现实技术?
  • Trait与生命周期
  • 学习vue3 第四章(reactive全家桶)
  • playwright自动化项目搭建
  • laravel(源码笔记)服务绑定和解析(依赖注入-反射,控制反转)
  • 【DFS+贪心】第十四届蓝桥杯省赛C++ B组《飞机降落》(C++)
  • 分享一款快速APP功能测试工具
  • @jsonView过滤属性
  • CSS盒模型深入
  • iOS | NSProxy
  • Kibana配置logstash,报表一体化
  • webpack4 一点通
  • 安装python包到指定虚拟环境
  • 闭包,sync使用细节
  • 闭包--闭包作用之保存(一)
  • 关于Flux,Vuex,Redux的思考
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 算法之不定期更新(一)(2018-04-12)
  • 一个完整Java Web项目背后的密码
  • 一些关于Rust在2019年的思考
  • 在weex里面使用chart图表
  • 自制字幕遮挡器
  • Nginx实现动静分离
  • 第二十章:异步和文件I/O.(二十三)
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​决定德拉瓦州地区版图的关键历史事件
  • #define、const、typedef的差别
  • (003)SlickEdit Unity的补全
  • (4)(4.6) Triducer
  • (C++17) optional的使用
  • (C语言)共用体union的用法举例
  • (pojstep1.1.2)2654(直叙式模拟)
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (办公)springboot配置aop处理请求.
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (理论篇)httpmoudle和httphandler一览
  • (万字长文)Spring的核心知识尽揽其中
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (一)RocketMQ初步认识
  • (一)插入排序
  • (译) 函数式 JS #1:简介
  • (转)负载均衡,回话保持,cookie
  • (转)人的集合论——移山之道