简介:vue管理后台权限控制具体思路与实现
今天我们来讲讲vue开发中权限控制的思路和具体的实现。在最早接触vue这一类前端框架时,我使用了一个单例来控制。在这个单例中拦截所有请求,然后判断是否登录,如果没有直接请求服务器判断是否登录。如果登录了直接继续请求其他接口,否则跳转登录页面。
这种方法看着好像还行,能解决登录问题,至于权限可以通过服务器判断,没有权限的返回权限不足的状态码,前端再提示用户没有权限。可是随着业务越来越大,客户要求越来越高,很多客户都要求,没有权限的页面需要隐藏,甚至有些客户会要求没有权限的按钮也要隐藏等等需求,上面的这一套权限控制的方案就不合适了。
最近看了一些vue-admin开源的管理后台,发现他们都是用路由的方式来控制。具体的思路就是在路由的钩子事件中vue-router官方叫导航守卫,在导航守卫中判断当前是否登录及用户是否有该页面的访问权限等等。最大的好处就是不用去拦截所有请求。
最要分为三个部分:请求类、vuex及导航守卫。
请求类:
这个类负责http请求的封装,其中还有服务器返回未登录的判断。有时候前端有登录信息但是服务器的登录信息却过期了,此时需要我们跳转登录页面重新登录
import axios from "axios";
import { Toast } from 'vant';
import router from '@/router/index.js'
export class request{
constructor() {
this.baseURL = '/api';
}
//设置请求的根目录或者说跟模块,这一个有可能需要改变
setBaseUrl(url){
this.baseURL = url
return this
}
//最总请求封装
http(url, params = null, method = 'post') {
let requestParam = { url, method }
if (params) {
if (method == 'post') {
requestParam.data = params;
} else {
requestParam.params = params;
}
}
return axios.create({
baseURL: this.baseURL, // url = base url + request url
timeout:0,
}).request(requestParam).then((res) => {
//很多后台都是通过返回code来判断服务器是否正常处理业务,code=0请求正常没有错误
if (res.data.code == 0) {
return Promise.resolve(res.data);
}
//code=401未登录跳转登录页面
if (res.data.code == 401) {
router.push({path:'/my/login'});
}
//其他错误抛出到外层
return Promise.reject(res.data)
}).catch(err => {
Toast.fail(err.msg?err.msg:'服务器异常');
return Promise.reject(err);
})
}
//post请求
post(url,param) {
return this.http(url,param)
}
//get请求
get(url) {
return this.http(url,null,'get')
}
}
vuex部分:
主要存储登录信息及当前用户可以访问的菜单列表,没有登录信息时通过接口获取。注意:如果接口返回没有登录的状态,上面的http请求封装的基类就会跳转登录页面
import Vuex from 'vuex';
import Vue from 'vue';
import user from '@/api/user.js'
Vue.use(Vuex);
export default new Vuex.Store({
state:{
//用户信息
user: null,
menu_list:null
},
getters: {
user: (state) => state.user,
menu_list: (state) => state.menu_list,
},
actions: {
//获取登录信息
getUserInfo() {
if (this.state.user) return Promise.resolve(this.state.user);
return this.dispatch('retrieveUser');
},
//重新获取登录信息
retrieveUser() {
return user.getUserInfo().then(res => {
this.state.user = res.data.user;
this.state.menu_list = res.data.menu_list;
return Promise.resolve(this.state.user);
});
}
}
});
导航守卫:
这个就是重点了,是否登录及是否有当前页面的权限,都在这里了,具体代码如下:
import router from './router';
import store from './vuex'
router.beforeEach(async (to, from, next) => {
//登录注册页面没有权限问题,直接执行
if (to.path == '/my/login' || to.path=='/my/register') {
next();
return;
}
//如果是从登录或者注册页面进入的需要重新获取登录信息(包括权限及菜单列表)
if (to.path == '/my/login' || to.path=='/my/register') {
//用户从登录页面进来的需要重新获取用户信息
store.state.user = null;
}
//通过获取用户信息来判断是否登录,没有登录的接口会返回未登录状态码,在请求基类中以判断未登录直接跳转登录页面
if (store.getters.user==null) {
//获取当前用户角色的菜单栏列表
await store.dispatch('getUserInfo');
}
next();
})
在菜单列表页面及个人中心页面大家可以通过vuex的mapGetters来实现获取登录信息及菜单列表,具体代码如下:
<template>
<div class="my">{{ user.nickname }}</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'my',
//计算属性结合vuex的mapGetters获取用户信息
computed: {
...mapGetters(['user']),
},
}
</script>
至于页面的按钮怎么实现隐藏?其实我们可以自定义按钮,所有页面都是用这个自定义的按钮。在自定义的按钮中判断当前页面是否显示或者说是否当前页面是否有这个按钮的权限,没有权限就直接隐藏,反之显示。具体代码我就不在这里显示,大家可以根据自己使用的UI框架(例如:element-ui)进行封装。
有遗漏或者不对的可以在我的公众号留言哦