核心想法:

登陆后获得用户角色,通过角色获得用户的权限,注入权限对应的路由。刷新页面,从localStorage用角色(更好的方式是通过token)再次获得所属权限,再次注入路由。在管理界面左端循环权限对应的路由菜单
localStorage存用户的信息(token),权限路由不会存。
所有的路由分为2种:
  • 公共路由:所有用户可以查看。
  • 权限路由:当前用户权限所属的路由。
实现控制的方式分两种:
  • 通过 vue-router addRoutes 方法注入路由实现控制
  • 通过 vue-router beforeEach 钩子限制路由跳转
一般来讲,需要采用第一种方式,addRoutes注入的方式,第二种每次判断,开销比较大,而且一次性拿不到角色对应的所有路由列表。这个列表需要再登陆后立即渲染在左边。


权限的控制分为好几种:
  • 一级菜单的权限控制,
  • 二级菜单的权限控制,
  • 按钮级别的权限控制。
控制方式有2种:
  • 后端返回路由控制列表
  • 前后端约定路由控制列表
代码:一级菜单的权限控制,前后端约定的方式确定角色能访问的路由。
routers/index.js

 

import Vue from 'vue'
import Router from 'vue-router'
import loginRoute from './modules/login.js';
import homeRoute from './modules/home.js'
import productionRoute from './modules/production.js';
import store from '../stores/index.js'; Vue.use(Router) //不需要权限的路由
export const constantRoutes = [loginRoute];
//需要权限的路由
//这里只是导出。实际上添加到router里在在store的permission里
export const asyncRoutes = [
homeRoute,
productionRoute,
];
console.log(asyncRoutes);
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
...constantRoutes,
]
})
router.beforeEach((to,from,next)=>{
let user = store.state.user.user;
let permissionRoutes= store.state.permission.permissionRoutes;
console.log(store.state);
console.log(user);
if(!user && to.path!=='/'){
next({
path:'/'
});
}else{
//刷新页面的情况
if(!permissionRoutes && user){
store.dispatch('generateRoutes',{
role:user.role
}) console.log(router);
console.log(to);
//这里写next没用
next({...to})
}else{
next();
} // next({...to, replace: true })
}
});
export default router;

  其中,productionRoute:

import Layout from '../../layouts/Index.vue'
const productionAdd = () => import('../../pages/production/Add.vue')
const productionList = () => import('../../pages/production/List.vue')
const productionTemplateComplete = () => import('../../pages/production/TemplateComplete.vue')
let routes = {
path: '/production',
component: Layout,
meta: {
title: '产品管理',
roles: [0, 1]
},
children: [
{
path: 'add',
component: productionAdd,
beforeEnter (to, from, next) {
console.log('router beforeEnter');
next();
},
meta: {
title: '产品新增'
}
},
{
path: 'list',
component: productionList,
meta: {
title: '产品列表'
}
},
{
path: 'templateComplete',
component: productionTemplateComplete,
meta: {
title: '产品新增完善'
}
}
]
} export default routes

  

stores/index.js
import Vue from 'vue'
import Vuex from 'vuex' import user from './modules/user.js'
import permission from './modules/permission.js' Vue.use(Vuex) export default new Vuex.Store({
modules: {
user,
permission,
}
})

  


stores/modules/user.js
const SET_USER = 'SET_USER' //登录成功
const CLEAR_USER = 'CLEAR_USER' //退出登录
import $ajax from '../../axios/index.js';
import store from '../index.js';
export default {
state: {
user:JSON.parse(localStorage.getItem('user')) || null
},
mutations: {
[SET_USER](state, user) {
state.user = user;
localStorage.setItem('user', JSON.stringify(user))
}, [CLEAR_USER](state) {
state.user = null;
localStorage.removeItem('user');
}
},
actions: {
login({commit}, param) {
console.log('action');
console.log(param);
return new Promise((resolve, reject) => {
//一期不做后台登陆,前端判断
// $ajax({
// url:api.login,
// data:{
// ...param
// }
// }).then(res=>{
// let user = res.data.data;
// commit(SET_USER, user);
// resolve();
// }).catch(res=>{
// reject();
// })
//前端验证用户名,密码
window.setTimeout(()=>{
if(param.username === 'huainanju' && param.password === 'huainanju123'){
let user = {
username:'管理员',
role:0
}
commit(SET_USER, user);
store.dispatch('generateRoutes',{
role:user.role
})
resolve();
}else{
reject();
}
},1000)
});
},
logout({commit}) {
commit(CLEAR_USER)
}
}
}

  


stores/modules/permisson.js
import {asyncRoutes} from '../../routers/index';
import router from '../../routers/index';
/**
* 递归过滤异步路由表,返回符合用户角色权限的路由表
* @param role
*/
function filterAsyncRoutes(role) {
const res = asyncRoutes.filter(route => {
return route.meta.roles.includes(role)
});
return res
} const permisssion = {
state:{
permissionRoutes:null
},
getter:{ },
mutations:{
SET_ROUTERS: (state, routes) => {
//添加路由
console.log('添加路由');
router.addRoutes(routes);
state.permissionRoutes = routes // 权限路由
},
},
actions:{
generateRoutes({ commit }, data) {
let {role} = data;
let routes = filterAsyncRoutes(role);
console.log(routes);
commit('SET_ROUTERS', routes)
}
}
} export default permisssion;

  

layouts/Left.vue
<template>
<el-aside style="min-height:100%;min-width:250px;" width="250px">
<el-menu :default-active="defaultActive"
background-color="#324157"
text-color="#bfcbd9"
active-text-color="#409EFF"
style="position:fixed;top:0;left:0;min-height: 100%;width:250px;z-index:100"
router>
<template v-for="(item,index) in permissionRoutes">
<!--一级菜单-->
<el-menu-item :index="item.path" v-if="item.children.length === 1 ">
<i class="el-icon-menu"></i>
<!-- <div>我是</div>-->
<span>{{item.meta.title}}</span>
</el-menu-item>
<!--多级菜单-->
<el-submenu :index="index+''" v-else>
<template slot="title">
<i class="el-icon-menu"></i>
<span>{{item.meta.title}}</span>
</template>
<template v-for="child in item.children">
<el-menu-item :index="item.path+'/'+child.path">{{child.meta.title}}</el-menu-item>
</template>
</el-submenu>
</template>
</el-menu>
</el-aside>
</template>
<script>
import {mapState} from 'vuex' export default {
data() {
return {
}
},
computed: {
...mapState({
'permissionRoutes':state=>state.permission.permissionRoutes
}),
defaultActive: function () {
if (this.$route.path.indexOf('/classInfo') >= 0) {
return 'classList'
}
return this.$route.path.replace('/org/', '');
}
},
created() {
window.setTimeout(()=>{
console.log(this.permissionRoutes);
},1000)
}
}
</script>

  


vue 权限管理的更多相关文章

  1. vue 权限管理深度探究

    实现思路如下:1.网页路由(route)中定义的每个路由都有meta属性,属性值防止可访问该路由的值.2.路由的全局前置守卫(beforeEach)会判断路由用户是否登录(未登录跳转至登录界面),以及 ...

  2. vue前后分离动态路由和权限管理方案

    需求 需要根据不同的角色来显示不同的菜单 问题 系统是前后分离模式开发的,出现了后端接口和前端路由都需要权限管理. 思路 后端的接口肯定得验证权限 在前端做好组件名和组件的映射 前端的路由通过后端发回 ...

  3. vue基于d2-admin的RBAC权限管理解决方案

    前两篇关于vue权限路由文章的填坑,说了一堆理论,是时候操作一波了. vue权限路由实现方式总结 vue权限路由实现方式总结二 选择d2-admin是因为element-ui的相关开源项目里,d2-a ...

  4. Spring Boot + Vue 前后端分离开发,权限管理的一点思路

    在传统的前后端不分的开发中,权限管理主要通过过滤器或者拦截器来进行(权限管理框架本身也是通过过滤器来实现功能),如果用户不具备某一个角色或者某一个权限,则无法访问某一个页面. 但是在前后端分离中,页面 ...

  5. vue 后台管理系统菜单权限管理

    来自:https://www.cnblogs.com/fqh123/p/11094296.html 侵删 login登录方法 login() { if (!this.username) { retur ...

  6. 权限管理UI

    vue+vuex+vue-router+EF的权限管理系统 演示网站 首先说下这个项目吧.如标题一样是基于VUE+.NET开发的框架,也是群友一直吼吼吼要一个vue版本的ABP框架.我们先来看看首页吧 ...

  7. vue权限路由实现方式总结二

    之前已经写过一篇关于vue权限路由实现方式总结的文章,经过一段时间的踩坑和总结,下面说说目前我认为比较"完美"的一种方案:菜单与路由完全由后端提供. 菜单与路由完全由后端返回 这种 ...

  8. SpringBoot + Apache Shiro权限管理

    之前配置过Spring + SpringMVC + JPA + Shiro后台权限管理 + VUE前台登录页面的框架,手动配置各种.xml,比较繁琐,前几天写了个SpringBootShiro的Dem ...

  9. Vue权限路由实现总结

    前言 年前完工了做了半年的铁路后台管理系统,系统整体业务比较复杂,这也是我到公司从 0 到 1 的 一个完整系统实践,做这个系统过程中踩了不少坑,也学到了很多. 做完这个系统没多久,紧接着又一个系统来 ...

随机推荐

  1. python pywin32学习笔记

    参考博客链接 https://blog.csdn.net/polyhedronx/article/details/81988948 参考博客链接 https://www.cnblogs.com/zha ...

  2. Censored! POJ - 1625 AC自动机+大数DP

    题意: 给出一n种字符的字典,有p个禁用的单词, 问能组成多少个不同的长度为m的合法字符串.(m<=50) 题解: 是不是个我们之前做的题目非常非常像,题意都一样. 直接将上次写的AC自动机+矩 ...

  3. mac系统升级导致无法在iOS设备中运行Safari Web 调试器

    macOS系统升级之后,可能会导致Safari开发选项中没有iOS设备,进而无法运行Safari Web 调试器. 此问题的解决办法: 请转到设置>常规>重置>重置位置和隐私.现在, ...

  4. centos 7 开机启动服务项优化

    1. 使用 systemctl list-unit-files 可以查看启动项 systemctl list-unit-files | grep enable 过滤查看启动项如下 abrt-ccpp. ...

  5. ASP.NET中的DEC加密解密过程

    本文章分享自 青青果树园的博客,地址是:http://www.cnblogs.com/qqingmu/archive/2008/01/10/1034168.html 我们做网页时经常会遇到URL传输( ...

  6. Echart使用过的属性总结

    改变坐标轴颜色与粗细: axisLine: { lineStyle: {//设置轴的颜色 color: '#CD0000', width: 1,//轴的宽度 } } 改变坐标轴上刻度的间隔与倾斜方向: ...

  7. 16进制与utf-8

    很多人将数据的存储.传输方式和展现形式混为一谈. 类似的16进制 2进制是讲内容在电脑里面的存储或者传输的一种格式, 而utf-8 gb2312 等是输出的展现的一种格式 不是一回事,另外 gbk包含 ...

  8. logger----->模块级别的函数

    #_author:star#date:2019/11/6#logger----->模块级别的函数#文件与屏幕同时显示日志信息import logginglogger=logging.getLog ...

  9. 2-sat——poj3678经典建图

    比较经典的建图,详见进阶指南 2-sat一般要用到tarjan来求强连通分量 /*2-sat要加的是具有强制关系的边*/ #include<iostream> #include<cs ...

  10. Duilib 入门教程: 怎么创建一个自定义的窗口

    一直想找一个好用UI 界面库,看过Direct UI,也想过 金山的界面库,后来找到了这个Duilib 现在的软件界面很多都是利用XML 来布局和定位. 像迅雷7,QQ,金山卫士等 [html] vi ...