ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
#### 前言:vue的权限管理,百度过很多,发现他们都是以角色为权限管理,但是要是新增角色就需要修改代码重复设定。 # :-: **准备** > 使用vue-cli3.0安装vue,并且使用element-ui。具体操作请查看element给vue-cli3.0提供的[插件链接](https://github.com/ElementUI/vue-cli-plugin-element)。 > 项目链接:[https://github.com/chentiewei/all/tree/develop/vue/vueAdminRouter](https://github.com/chentiewei/all/tree/develop/vue/vueAdminRouter) # :-: **正文** > 项目文件列表,直接上图 ![](https://box.kancloud.cn/2cbc895bb439b163ce9913f59fd43a37_476x930.png) > 第一步,先做一个登陆页面,并创建账号,每个账号有不同的权限。 > 新建login.vue页面,为登陆页面,很一般就是一个普通的登陆页面 ``` <template> <div class="login_box"> <el-form label-position="right" label-width="60px" :model="loginfrom"> <el-form-item label="用户名"> <el-input v-model="loginfrom.username"></el-input> </el-form-item> <el-form-item label="密码"> <el-input type="password" v-model="loginfrom.password"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="submituUserInfo(loginfrom)">登录</el-button> </el-form-item> </el-form> <div class="msg"> <span>账号:admin</span> <span>账号:a</span> <span>账号:b</span> <span>账号:c</span> </div> </div> </template> <script> export default { name: 'login', data () { return { loginfrom:{ username:'', password:'123456' } } }, methods:{ submituUserInfo(data){//登陆提交方法 this.$store.dispatch('Logins',data).then(res => {//vuex登陆方法 this.$router.push({ path: '/' });//登陆成功默认跳转页面 }).catch(() => { }) } } } </script> ``` > login.js里面包含了用户的登陆信息,一般是由ajax完成的,但是我们这边简化他所以使用固定的登陆信息。 > 里面的role数组就是他的权限了 ``` /*暴露接口为loginByUserInfo*/ export const loginByUserInfo = [ {"id": 1, "username": "admin", "pew": 123456, "role": [{ "name":"home"},{ "name":"red"}, {"name": "yellow"}, {"name": "blue"},{ "name":"all"}] , "introduce":"我可以看见全部页面"}, {"id": 2, "username": "a", "pew": 123456, "role": [{ "name":"home"},{"name": "blue"},{ "name":"all"}] , "introduce":"我可以看到home,blue和all页面"}, {"id": 3, "username": "b", "pew": 123456, "role": [{ "name":"home"},{ "name":"red"}], "introduce":"我可以看见red和home页面"}, {"id": 3, "username": "c", "pew": 123456, "role": [{ "name":"home"},{ "name":"red"},{ "name":"all"}], "introduce":"我可以看见home,red和all页面"}, ] ``` > router.js要注意,里面有2个模块一个为公共router,一个为私有router,而私有router是经过,和后台交互获取权限我们这里用了login.js来模拟。 ``` import Vue from 'vue' import Router from 'vue-router' /*页面声明*/ import home from '@/views/home' import login from '@/views/login' import red from '@/views/red' import yellow from '@/views/yellow' import blue from '@/views/blue' import all from '@/views/all' import all1 from '@/views/all1' import all2 from '@/views/all2' Vue.use(Router) /*公有router*/ export default new Router({ routes: [ { path: '/login', name: 'login', component: login } ] }) /*私有router*/ export const powerRouter = [ {path: '/', name: 'home', component: home}, {path: '/red', name: 'red', component: red}, {path: '/yellow', name: 'yellow', component: yellow}, {path: '/blue', name: 'blue', component: blue}, { path: '/all', name: 'all', component: all, children: [ {path: '/all1', name: 'all1', component: all1,}, {path: '/all2', name: 'all2', component: all2,} ] } ]; ``` > store里面包含登陆,登出,权限方法,已经变量用户,权限和新权限列表。 ``` import Vue from 'vue' import Vuex from 'vuex' import { loginByUserInfo }from '@/api/login' Vue.use(Vuex) export default new Vuex.Store({ state: { username: sessionStorage.getItem('USERNAME'), role: JSON.parse(sessionStorage.getItem('ROLE')), newrouter: [], }, getters: { username: state => state.username, role: state => state.role, newrouter: state => state.newrouter }, mutations: { SET_USERNAME:(state, username) => { state.username = username; }, SET_ROLE:(state, role) => { state.role = role; }, SET_NEWROUER:(state, newrouter) =>{ state.newrouter = newrouter; }, }, actions: { Logins({ commit }, info){/*登陆方法*/ return new Promise((resolve, reject) => { let data={}; loginByUserInfo.map(function (item) { //获取所以用户信息 if(info.username === item.username || info.pew === item.pew){ commit('SET_USERNAME',item.username); //将username和role进行存储 sessionStorage.setItem('USERNAME', item.username); //存入 session commit('SET_ROLE',item.role); sessionStorage.setItem('ROLE',JSON.stringify(item.role)); //存入 session return data={username:item.username,introduce:item.introduce}; }else{ return data; } }); resolve(data); }).catch(error => { reject(error); }); }, Roles({ commit }, newrouter){ return new Promise((resolve, reject) => { commit('SET_NEWROUER',newrouter); //存储最新路由 resolve(newrouter); }).catch(error => { reject(error); }); }, Logout({ commit, state }) {/*登出方法*/ return new Promise((resolve, reject) => { commit('SET_USERNAME',''); commit('SET_ROLE',''); commit('SET_NEWROUER',[]); sessionStorage.removeItem('USERNAME'); sessionStorage.removeItem('ROLE'); resolve(); }).catch(error => { reject(error); }); } } }) ``` > main.js使用router.beforeEach来监控每个页面是不是达到要求 > 先引入router.js的powerRouter私有router。并且引入vuex ``` import { powerRouter } from './router'; import store from './store' ``` ``` router.beforeEach((to, from, next) => { let _role=store.getters.role if(_role){ //判断role 是否存在 if(store.getters.newrouter.length !== 0){//判断vuex的newrouter是否为空 next(); }else{ let newrouter=[]; _role.forEach((i)=>{ powerRouter.forEach((k)=>{ if(k.name==i.name){//判断用户登陆信息role有哪些,用name比对。 newrouter.push(k) } }) }) router.addRoutes(newrouter) //添加动态路由 store.dispatch('Roles',newrouter).then(res => {//使vuex的newrouter保留私有rouer列表 next({ ...to }) }).catch(() => { }) } }else{ if (['/login'].indexOf(to.path) !== -1) { next() } else { next('/login') } } }) ``` > 最后以home.vue结尾,这里我特别注意,为什么使用vuex的newrouter列表进行循环而不是用router列表直接循环呢?因为我们使用的是addRouters,此方法如何直接使用router列表循环不会更新,所以我们使用vuex的newrouter。 ``` <template> <div> <div class="header"> <div v-for="(v,i) in newrouter" :key="i"><!--vuex的newrouter--> <router-link :to="{name:v.name}" v-if="!v.children">{{v.name}}</router-link> <div v-else-if="v.children">{{v.name}}</div><!--判断是不是有子router--> <div v-for="(k,j) in v.children"><!--判断是不是有子router--> <router-link :to="{name:k.name}">{{k.name}}</router-link> </div> </div> </div> <div class="main"> <router-view></router-view> </div> <el-col :span="1" class="out"> <div class="logout_box" @click="logout()">退出</div> </el-col> </div> </template> <script> import { mapGetters } from 'vuex'; export default { name: 'home', data () { return { newrouter:this.$store.state.newrouter//vuex的newrouter第一种展现形式 } }, created(){ }, computed: { /*...mapGetters([//vuex的newrouter第二种展现形式 'newrouter' ])*/ }, methods: { logout(){//为登出按钮 this.$store.dispatch('Logout').then(() => { this.$router.push({ path: '/login' }); }).catch(err => { this.$message.error(err); }); } }, mounted(){ } } </script> ``` # :-: **功能加强** > 上面代码有缺陷,仔细查看的会发现他不能控制子路由。也不能控制一些添加删除页面。 > 我们需要修改router.js和main.js > 项目链接:[https://github.com/chentiewei/all/tree/develop/vue/vueAdminRouter2](https://github.com/chentiewei/all/tree/develop/vue/vueAdminRouter2) > router.js的powerRouter修改为**powerRouterLazy** ``` export function powerRouterLazy(name) { switch (name) { case 'home': return {path: '/', name: 'home', component: home} break; case 'red': return {path: '/red', name: 'red', component: red} break; case 'yellow': return {path: '/yellow', name: 'yellow', component: yellow} break; case 'blue': return {path: '/blue', name: 'blue', component: blue} break; case 'all': return {path: '/all', name: 'all', component: all,children: []} break; case 'all1': return {path: '/all1', name: 'all1', component: all1} break; case 'all2': return {path: '/all2', name: 'all2', component: all2} break; } } ``` > main.js方法 ``` let generaMenu = (obj,data) =>{ /*循环router方法*/ data.forEach((v,i)=>{ obj.push(powerRouterLazy(v.name)) if(v.children){ generaMenu(obj[i].children,v.children)//递归children } }) } router.beforeEach((to, from, next) => { let _role=store.getters.role if(_role){ //判断role 是否存在 if(store.getters.newrouter.length !== 0){//判断newrouter是否为空 next() }else{ let newrouter=[] generaMenu(newrouter,_role)/*router循环*/ router.addRoutes(newrouter) //添加动态路由 store.dispatch('Roles',newrouter).then(res => { next({...to}) }).catch(() => { }) } }else{ if (['/login'].indexOf(to.path) !== -1) {/*是否为login*/ next() } else { next('/login') } } }) ``` > 上述代码可以控制,新增,编辑,添加,和子路由。这样就是一个完整的权限管理了 # # ヘ(;´Д`ヘ) (/゚Д゚)/ (\*゜ロ゜)ノ Σ(  ̄д ̄;) #### 小结:上述代码想法是,**用户登陆--获取用户权限--跳转使用beforeEach判断权限--判断完成提交vuex--最后页面根据vuex变量循环**,这边其实还有一个思路,在router注册前就把 权限router给整理出来,然后在注册,这样更加的简单,清晰。