常见的后台系统中,会存在不同的用户角色,如超级管理员、普通用户,这些用户角色的权限是不同的,所以可以操作或显示的模块也不一致。这里采用如下后台管理系统框架作为模板

地址:https://github.com/PanJiaChen/vue-admin-template

简单说下需求,后台菜单如下图,要求系统中存在两类用户,管理员和普通员工,管理员登录系统可见所有菜单选项,普通用户仅可见首页菜单项。

项目左侧菜单Sidebar组件代码如下,用v-for遍历当前路由实例路由配置this.$router.options.routes传递给<sidebar-item/>,进行展示,这里不做详细介绍,

<el-scrollbar wrap-class="scrollbar-wrapper"><el-menu:default-active="activeMenu":collapse="isCollapse":background-color="variables.menuBg":text-color="variables.menuText":unique-opened="false":active-text-color="variables.menuActiveText":collapse-transition="false"mode="vertical"><sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" /></el-menu></el-scrollbar><script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'export default {components: { SidebarItem, Logo },computed: {...mapGetters(['sidebar']),routes() {return this.$router.options.routes;},}
}

由此可知要实现菜单栏的动态展示,在路由配置文件中,就不能将项目中所有的路由配置对象写在一起,这里将项目中的路由配置拆分成三类,如下所示。分别是constantRoutes常量路由,存放所有用户都可见的路由包括首页,登录页,404页;asyncRoutes异步路由,存放不同的用户需要过滤出筛选的路由;anyRoutes任意路由,当路径出现错误的时候重定向到404页面。这样就可以灵活处理路由配置信息了。

router/index.js

export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: '首页', icon: 'dashboard' }}]},]export const asyncRoutes = [{name: 'Acl',path: '/acl',component: Layout,redirect: '/acl/user/list',meta: {title: '权限管理',icon: 'el-icon-lock'},children: [{name: 'User',path: 'user/list',component: () => import('@/views/acl/user/list'),meta: {title: '用户管理',},},......]},{path:'/product',component:Layout,name:'Product',meta: { title: '商品管理', icon: 'el-icon-goods' },children:[{path:'tradeMark',name:'TradeMark',component:() => import('@/views/product/tradeMark'),meta:{title:'品牌管理'}},......]},
];export const anyRoutes = [// 404 page must be placed at the end !!!{ path: '*', redirect: '/404', hidden: true }
];const createRouter = () => new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),routes: constantRoutes
})

在用户登录系统后,浏览器会根据用户的token信息获取用户的详细信息,里面除了用户的基本信息外,还包括该用户可以访问的菜单列表(Array),以及用户能够操作的按钮列表。

请求行为在vuex的actions中进行,在登录页面派发该actons,在aciions中将响应的用户信息提交mutations。

const getDefaultState = () => {return {token: getToken(),name: '',avatar: '',routes:[],  // 服务器返回的菜单标记信息buttons:[],  // 服务器返回的按钮标记信息role:[],  // 服务器返回的角色信息}
}const state = getDefaultState()
const mutations = {RESET_STATE: (state) => {Object.assign(state, getDefaultState())},USER_INFO: (state,info) => {state.name = info.name;state.avator = info.avator;state.routes = info.routes;   // 菜单权限标记state.buttons = info.buttons;  // 按钮权限标记state.role = info.role;  // 用户角色
},
const actions = {// get user infogetInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo(state.token).then(response => {const { data } = responseif (!data) {return reject('Verification failed, please Login again.')}// commit('USER_INFO',data);resolve(data)}).catch(error => {reject(error)})})},
}

拿到了服务器返回的可显示的异步路由标记信息后,接下去要做的就是将其和项目中所有的异步路由信息进行对比,得到最终需要展示的异步路由信息,这里在登录后再提交一个mutations,命名为SEY_RESULTASYNCROUTES,传给mutations一个方法computedAsyncRoutes,在这个方法中做路由的信息对比,将当前用户要显示的异步路由作为返回值返回。

getInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo(state.token).then(response => {const { data } = responseconsole.log(response.data);if (!data) {return reject('Verification failed, please Login again.')}// commit('USER_INFO',data);commit('SEY_RESULTASYNCROUTES',computedAsyncRoutes(asyncRoutes,data.routes));resolve(data)}).catch(error => {reject(error)})})},

定义computedAsyncRoutes方法如下,将异步路由asyncRoutes引入,遍历asyncRoutes数组,将每一个路由的name和服务器传来的标记信息routes挨个对比(indexOf方法),过滤出服务器标记数组中包含的路由信息;

这里值得注意一点,由于路由存在二级甚至三级路由,这些路由是写在路由配置对象的children属性中,它们一样也要遍历并对比判断它们是否需要显示,需要递归调用computedAsyncRoutes方法,对每个以及路由的children再次进行过滤。

import { resetRouter,asyncRoutes,anyRoutes,constantRoutes } from '@/router'
// 两个数组进行对比,计算出当前用户显示哪些异步路由
const computedAsyncRoutes = (asyncRoutes,routes) => {return asyncRoutes.filter((item) => {// 服务器返回的数组中包含的路由信息if(routes.indexOf(item.name) !== -1) {// 如果存在多级路由,递归if(item.children && item.children.length) {item.children = computedAsyncRoutes(item.children,routes);}return true;}})
}

这样提交到的SEY_RESULTASYNCROUTES这个mutations中就可以拿到上述处理完后的路由配置信息asyncRoutes了,但还需要做路由的合并操作,就是将先前定义的常量路由、任意路由和刚刚对比过滤完的异步路由三者进行合并(数组的concat方法),形成一个最终完整的路由信息,并给当前项目添加这个路由规则router.addRoutes(state.resultAllRoutes)

import router from '@/router'
const getDefaultState = () => {return {token: getToken(),name: '',avatar: '',routes:[],  // 服务器返回的菜单标记信息buttons:[],  // 服务器返回的按钮标记信息role:[],  // 服务器返回的角色信息resultAsyncRoutes:[],resultAllRoutes:[]}
}const state = getDefaultState();mutations:{// 最终计算出的异步路由SEY_RESULTASYNCROUTES(state,asyncRoutes){// vuex保存当前用户的异步路由state.resultAsyncRoutes = asyncRoutes;// 计算出当前用户的所有路由state.resultAllRoutes = constantRoutes.concat(state.resultAsyncRoutes,anyRoutes);// 给路由添加新的路由router.addRoutes(state.resultAllRoutes);}
}

此时登陆后依旧无法正确显示左侧的菜单。

虽然此时正确的路由已经存在于router实例中,但左侧导航栏<Sidebar>组件遍历的依旧只有首页菜单,那是因为在routes/index.js中注册是常量路由如下所示,而修改操作router.addRoutes(state.resultAllRoutes)是异步操作以后的结果,在sidebar组件中通过 this.$router.options.routes只能获取初始的常量路由

router/index.js:

const createRouter = () => new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),routes: constantRoutes
})

sidebar.vue

export default {components: { SidebarItem, Logo },computed: {routes() {return this.$router.options.routes;},}
}

只需将获取方式改为仓库中最新的路由配置信息this.$store.state.user.resultAllRoutes

sidebar.vue

routes() {return this.$store.state.user.resultAllRoutes;
},

这样就实现了不同身份的用户登录后显示不同的菜单的效果。

此外,要在项目中实现按钮权限,即同一个按钮,有的用户显示按钮,有的用户不显示,只要拿到上述的buttons数组,在对应的按钮标签上使用v-show进行判断即可

<button v-show="$store.state.xxxModule.buttons.indexOf('对应的按钮标签名')">删除</button>

【vue.js】vue后台项目权限功能实现思路相关推荐

  1. vue vuex vue-router后台项目——权限路由(超详细简单版)

    项目地址:vue-simple-template 共三个角色:adan barbara carrie 密码全是:123456 adan 拥有 最高权限A 他可以看到 red , yellow 和 bl ...

  2. 干货|6个牛逼的基于Vue.js的后台控制面板,接私活必备

    JavaEE擅长的就是企业级应用,作为一个Java程序员,如果想自己徒手撸一个ERP.WMS之类的系统还是有一点挑战的,不过今天松哥要给大家介绍几款牛逼的基于Vue.js的后台管理控制面板,掌握这几款 ...

  3. Vue.js快速入门+项目实战(源码)

    Vue.js电影网站项目 github 链接(如果觉得有用记得start哦~): 项目源代码链接 目录 前言 安装 Vue.js 1.Vue.js主要特性 2.Vue.js实例 3.Vue.js路由 ...

  4. Vue.js经典开源项目汇总

    Vue.js经典开源项目汇总   Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计 ...

  5. 【前端】Vue.js经典开源项目汇总

    Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) ...

  6. html鼠标悬浮更换图片,Vue.js鼠标悬浮更换图片功能

    最近自己做的项目中设计师要求分类栏中鼠标悬停更换图片,大致实现出来的效果就是这样: 这个在jQuery中是个很简单的事,但是在vue中我还是第一次实现. 首先将所有的选中后图片都覆盖到没选中图片上 c ...

  7. 基于 vue.js + elementUI 后台管理系统 (html)模板

    mq-admin vue.js + elementUI 后台管理系统模板 前言 今年年初刚转型学前端,业务需要做一个后台管理系统.好嘛,GitHub,码云先爬一波,发现了许多大佬的作品.那时也刚转型走 ...

  8. vue.js电商项目--美丽购物街day01首页制作

    vue.js电商项目--美丽购物街day01 首页效果如图 划分目录结构 vue.config.js配置文件别名 App.vue文件 router文件下的index.js 封装网络请求 Home.vu ...

  9. Awesome Vue.js vue.js学习资源链接大全 中文

    策划列表相关的vue.js可畏的事 资源 官方资源 外部资源 工作门户 社区 会议 播客 官方的例子 教程 实例 书 项目采用vue.js 开源 商业产品 应用/网站 互动体验 企业使用 组件& ...

最新文章

  1. mysql docker自动化_docker自动化部署
  2. Keywords: Flash( Scaleform ) UI
  3. 用html5交换两个变量的值,Python判断两个对象相等的原理 python交换两个变量的值为什么不用中间变量...
  4. 中查出所有姓张的学生为啥查不出来_只有笔试成绩没有面试成绩是什么原因 教师资格面试成绩怎么查...
  5. Java NIO学习笔记 三 散点/收集 和频道转换
  6. Angular之双向数据绑定(上)
  7. 【CCCC】L3-021 神坛 (30分)计算几何+求三角形面积(极角排序)
  8. 安装 | Android studio 3.5.2安装教程
  9. canvas--初识canvs、绘制:线型、简单图形、渐变背景颜色、绘制动画、canvs形变、事件绑定
  10. 详细记录基于vue+nodejs+mongodb构建的商城学习(三)基于项目的vue框架梳理
  11. excel 实现内建函数
  12. 数据可视化—绘制简单的折线图
  13. SpringBoot整合Tomcat中的组件
  14. MFC对话框标题栏颜色自绘,标题栏由过渡色组成,自绘关闭按钮
  15. lack名词形式_lack的用法
  16. [转]如何进行人脉管理
  17. FastDDS(9)Security安全性
  18. 光时域反射仪都有什么功能
  19. 威力曲面sw2020_威力曲面powersufacing_沐风网
  20. ElasticSearch(六)组合多查询(must, should, must_not, bool, filter)

热门文章

  1. 文章内容页调用所属栏目地址的标签
  2. CSS基础必备盒模型及清除浮动
  3. seaJS简介和完整实例
  4. qt5 + vs2015自定义控件错误:undefend interface
  5. 初识java-循环结构(二):6
  6. Flexible 弹性盒子模型之CSS align-self 属性
  7. img下出现几像素空白的问题
  8. CodeBlocks 更改 gui 程序为 命令行
  9. 可视化篇(二)———使用matplotlib绘制常用3D图形及案例
  10. 跨链Cosmos(6)ABCI 原理