版本环境
vue的版本是^2.6.12,将会使用到Vue.use()、Vue.directive()
适用环境
页面某些按钮,需要受到当前登录用户的“角色”“权限”的影响,通过store获取角色role和权限permission,通过自定义指令的方式,控制某一个组件的显示与隐藏。
文件架构
index.js文件,src/index.js
directive文件夹中三个文件,分别是src/directive/hasPermi.js、src/directive/hasRole.js、src/directive/index.js
前置配置
需要配合store使用,store.getter.roles角色,store.getters.permissions权限
文件内容
src/index.js文件
主要用于注册组件。用注册插件的方式,一次性注册两个指令
import Vue from 'vue'
import permission from './directive'
Vue.use(permission)
// 省略其他
src/directive/index.js文件
import hasRole from './hasRole'
import hasPermi from './hasPermi'
const install = function(Vue) {
Vue.directive('hasRole', hasRole)
Vue.directive('hasPermi', hasPermi)
}
if (window.Vue) {
window['hasRole'] = hasRole
window['hasPermi'] = hasPermi
Vue.use(install); // eslint-disable-line
}
export default install
vue2的官方文档对Vue.directive()做了解释,第一个参数为指令名称,文件中设置了两个指令,在组件中可以使用“v-hasPermi”和“v-hasRole”。就像使用v-if一样来控制组件。
第二个参数为一个function方法,入参为VUE对象。
控制的逻辑就是很简单的删除VNode下面的所有Element元素。在另外两个文件中可以具体看到。
src/directive/hasRole.js文件
/**
* 角色权限处理
*/
import store from '@/store'
export default {
inserted(el, binding, vnode) {
const { value } = binding
const super_admin = "admin";
const roles = store.getters && store.getters.roles
if (value && value instanceof Array && value.length > 0) {
const roleFlag = value
const hasRole = roles.some(role => {
return super_admin === role || roleFlag.includes(role)
})
if (!hasRole) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`请设置角色权限标签值"`)
}
}
}
inserted是钩子函数,在官方文档中有说明
在插入父节点的时候,判断是否有权限,如果没有的话,通过vnode删除下面的所有子节点。
考虑到可能被多个角色控制,因此v-hasRole要传入一个数组,通过判断是否具有指定的字符串,只要满足其中一个便显示。否则通过el对象拿到parentNode节点,通过父节点的removeChild移除自身。
src/directive/hasPermi.js文件
/**
* 操作权限处理
*/
import store from '@/store'
export default {
inserted(el, binding, vnode) {
const { value } = binding
const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions
if (value && value instanceof Array && value.length > 0) {
const permissionFlag = value
const hasPermissions = permissions.some(permission => {
return all_permission === permission || permissionFlag.includes(permission)
})
if (!hasPermissions) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`请设置操作权限标签值`)
}
}
}
和角色控制一样的判断逻辑,不同的是,按钮这种权限,可以通过拼接或者特定字符指定。
假设一个list菜单,下面有两个页面add页面和edit页面,里面都有一个功能相同的按钮,但是想细致的区分两个权限。则,可以设置一个按钮的权限为“list:add:btn"另一个的按钮权限为"list:edit:btn”。对应的,如果同时有这两个的权限,可以将两个的值都设置为"list:all:btn"。
代码示例,v-hasRole也是一样
<el-button v-hasPermi="['list:add:btn']">确认</el-button>
<el-button v-hasPermi="['list:edit:btn']">确认</el-button>
精细到每一个组件的控制,还是按角色来粗略区分。要按实际业务需要,以及方便程度。