vue 权限管理

vue


核心想法:

1.登陆后获得用户角色,通过角色获得用户的权限,注入权限对应的路由。
2.刷新页面,从localStorage用角色(更好的方式是通过token)再次获得所属权限,再次注入路由。在管理界面左端循环权限对应的路由菜单。
3.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 权限管理 的全部内容, 来源链接: utcz.com/z/375272.html

回到顶部