在咱们构建项目以后,如今开始撸代码了!很是抱歉拖了那么久,最近麻烦事情比较多,如今是终于空闲那么一点点了!在写这篇权限控制的时候,想了好久,不知道该如何下手才能更好的表达出来,感受代码有点绕,多是本身对于vue不是很熟悉吧,开文已经说了,这个项目是练手项目,有不足之处欢迎指出来。javascript
先看效果图,看看是否是你要的。
vue
假设后台界面是这样
java
在这里值得注意的是:在未登陆的时候,本项目的控制逻辑是只能显示登陆这个页面,输入其它连接也是不会跳转的!
效果以下:
ios
按照我我的理解逻辑就是在登陆以后根据用户信息得知对应的权限,实际上就是控制用户对应的路由,从而在界面上显示出。
例如拿上边的图来讲:
1.假设admin
是超级管理员,那么获得的就是全部的路由,界面显示(概况,组件,权限)
2.normal
是普通管理员,只能看见部分,界面显示(概况,组件)
npm
大概的逻辑就是这样,在获取权限以前,确定要先登陆,否则怎么知道你是谁呢?你能干吗呢?axios
只追求功能实现的,能够先随便弄两个输入框加上一个肯定按钮,给肯定按钮绑定click事件。有强迫症的我,仍是给美化了下,而后在提交以前进行表单验证,效果以下:(帐号是随机生成的)
数组
验证完成,实现登陆以后,咱们进行用户信息保存操做。浏览器
this.$http.post('/login', _data).then((response) => {
// 保存用户信息(StoreUser/setUser)
this.$store.dispatch('StoreUser/setUser', response.data).then(() => {
});
});
登陆成功后,服务端会返回客户的信息,用了VUEX
这个状态管理工具,优先保存在一个用户的状态信息,由于有可能在多处会用到这个信息,例如我的中心等等页面。cookie
const state={
'isLogin':false
};
const mutations = {
'SET_USER':function(state,userData){
state = _.assign(state,userData);
Cookie.set('accountData', state);
},
'REMOVE_USER':function(state){
state = _.assign(state,{
'isLogin':false
});
Cookie.remove('accountData');
}
};
const actions = {
'setUser':function({commit},userData){
commit('SET_USER',userData);
},
'removeUser':function({commit}){
commit('REMOVE_USER');
}
};
再将这个用户信息保存Cookie中,用作话处理,这样下次打开页面或者刷新页面的时候能记住用户的登陆状态。这里这里使用了js-cookie这个工具。app
获取用户信息,就能知道这个用户的权限范围了,而后咱们根据这个权限生成对应的路由表
this.$store.dispatch('StoreAddRoutes/getRoutes',_roles).then(() => { // 根据_roles权限生成可访问的路由表 // 动态添加可访问路由表 this.$router.addRoutes(this.$store.getters.addRoutes); // 黑科技 window.location.replace('/'); });
this.$store.dispatch('StoreAddRoutes/getRoutes',_roles).then(() => { // 根据_roles权限生成可访问的路由表 // 动态添加可访问路由表 this.$router.addRoutes(this.$store.getters.addRoutes); // 黑科技 window.location.replace('/'); });
StoreAddRoutes/getRoutes
这个方法是如何呢?
const actions = {
'getRoutes':function({commit},roles){
if (_.indexOf(roles, 'admin') !== -1) {
commit('SET_ROUTERS',adminRoutes());
} else {
commit('SET_ROUTERS',normalRoues());
}
}
};
经过StoreAddRoutes/getRoutes
返回的路由信息this.$store.getters.addRoutes
,主要是用了vue2.2.0之后新增了router.addRoutes
的方法进行动态添加,注意addRoutes()这个方法添加是数组!
重点是这句:this.$router.addRoutes(this.$store.getters.addRoutes);
在actions
中,咱们根据权限分了adminRoutes
和normalRoutes
这两个路由表,分别对应超级管理员
和普通管路员
从上面获取能够看出由权限分出的两个路由表,那么这两个adminRoutes
和normalRoutes
是怎么来的呢?
/**
* [AdminRouter 超级管理员]
* @type {Array} */
export function adminRoutes() {
layoutObj.children = layoutObj.children.concat([
RoleRouter
]);
return [commonRoutes(),layoutObj];
}
/**
* [NormalRouer 普通用户]
* @type {Array} */
export function normalRoues() {
return [commonRoutes(),layoutObj];
}
其中commonRoutes()
是公共页面,例如登陆,404等页面
/**
* 公共路由
* @type {Array} */
export function commonRoutes() {
return LoginRouter;
}
而layoutObj
这个就是整个布局信息,包括:侧边栏SideBar
,右边帮助Help
,底部Foote
r和中间内容Comtainer
import LoginRouter from '@/pages/login/router.js'; import HomeRouter from '@/pages/home/router.js'; import RoleRouter from '@/pages/role/router.js'; import ModuleRouter from '@/pages/module/router.js'; const Comtainer = resolve => require(['@/components/layout/layout'],resolve); const SideBar = resolve => require(['@/components/layout/sidebar'],resolve); const Help = resolve => require(['@/components/layout/help'],resolve); const Footer = resolve => require(['@/components/layout/footer'],resolve); let layoutObj = { 'path': '/', 'name': 'layout', 'components': { 'default' : Comtainer, 'sidebar' : SideBar, 'help' : Help, 'appFooter': Footer }, 'redirect': '/index', 'children': [ HomeRouter, ModuleRouter ] };
import LoginRouter from '@/pages/login/router.js'; import HomeRouter from '@/pages/home/router.js'; import RoleRouter from '@/pages/role/router.js'; import ModuleRouter from '@/pages/module/router.js'; const Comtainer = resolve => require(['@/components/layout/layout'],resolve); const SideBar = resolve => require(['@/components/layout/sidebar'],resolve); const Help = resolve => require(['@/components/layout/help'],resolve); const Footer = resolve => require(['@/components/layout/footer'],resolve); let layoutObj = { 'path': '/', 'name': 'layout', 'components': { 'default' : Comtainer, 'sidebar' : SideBar, 'help' : Help, 'appFooter': Footer }, 'redirect': '/index', 'children': [ HomeRouter, ModuleRouter ] };
看完整个路由表的信息,这样就能很容易经过不一样的权限,放置不一样的页面路由,从而进行权限控制。
注意到上边我提到的黑科技没?
在动态添加完路由表以后,进行页面首页跳转。而不是使用this.$router.push()这个方法跳转?由于若是使用这个方法,会一直警告有重复路由的警告,看了源码大概是觉得你addRoutes()这个方法,框架并无提供删除路由的方法,添加了就一直会存在浏览器中,所以用黑科技,将页面刷新。
// 黑科技
window.location.replace('/');
router.beforeEach((to, from, next) => {
if (Cookie.getJSON('accountData') && Cookie.getJSON('accountData').isLogin) { // 判断是否有cookie
next();//当有用户权限的时候,说明全部可访问路由已生成 如访问没权限的全面会自动进入登陆页面
} else if (to.path === '/login') {
next();
} else {
next('/login'); //当有用户权限的时候,说明全部可访问路由已生成 如访问没权限的全面会自动进入404页面
}
});
拦截器是为了防止用户直接输入地址进行跳转,由于你都没登陆,怎么可能就让你进行访问呢!!当cookie存在用户信息的时候,说明是登陆状态,能够进行正常访问,若是不是登陆状态,那么只能跳转到登陆状态