目录
项目需求
项目中有写组件的渲染要根据角色或者部门的权限进行控制。那么可以使用自定义指令去实现该目标。
组件设计
自定义角色权限指令
指令逻辑按照实际业务逻辑为准
import store from '@/store'
const validateRole = (el, binding) => {
let roles = []
// 1.get value from directive
const directiveVal = binding.value
// 2. get value's type
const directiveValType = Object.prototype.toString.call(binding.value)
// 3.create roles data
switch (directiveValType) {
case '[object Array]':
roles = directiveVal
break
case '[object Number]':
roles.push(directiveVal)
break
default:
roles = (binding.value+'').split('|')
break
}
// unique roles data
roles = [...new Set(roles)]
// 4. get current user's roles from store
const storeRoles = store.getters.roles || []
let userRoles = storeRoles.map((item) => item.id)
// 5. default hidden
let showFlag = false
if (userRoles.length) {
// unique current user roles data
userRoles = [...new Set(userRoles)]
// cross result
const crossResult = roles.filter((item) => userRoles.indexOf(item) >= 0)
// show element when cross resule exsist
if (crossResult && crossResult.length) showFlag = true
}
// remove element
if (!showFlag) {
el.parentNode && el.parentNode.removeChild(el)
}
}
export default {
inserted: function (el, binding) {
validateRole(el, binding)
},
updated: function (el, binding) {
validateRole(el, binding)
}
}
增强功能
还可以使用bind中的参数,用来区分权限策略,传递arg默认为include-表示包含该角色才能显示组件;传递arg:exclude-表示除了指定角色外都能显示
import store from '@/store'
const validateRole = (el, binding) => {
let roles = []
// 1.get value from directive
const directiveVal = binding.value
// get directive ruler include | exclude
const directiveRuler = (binding.arg || 'include').toLowerCase()
// 2. get value's type
const directiveValType = Object.prototype.toString.call(binding.value)
// 3.create roles data
switch (directiveValType) {
case '[object Array]':
roles = directiveVal
break
case '[object Number]':
roles.push(directiveVal)
break
default:
roles = (binding.value + '').split('|')
break
}
// unique roles data
roles = [...new Set(roles)]
// 4. get current user's roles from store
const storeRoles = store.getters.roles || []
let userRoles = storeRoles.map((item) => item.id)
// 5. default hidden
let showFlag = false
if (userRoles.length) {
// unique current user roles data
userRoles = [...new Set(userRoles)]
// cross result
const crossResult = roles.filter((item) => {
if (directiveRuler == 'include') {
return userRoles.indexOf(item) >= 0
}
if (directiveRuler == 'exclude') {
return userRoles.indexOf(item) < 0
}
return false
})
// show element when cross resule exsist
if (crossResult && crossResult.length) showFlag = true
}
// remove element
if (!showFlag) {
el.parentNode && el.parentNode.removeChild(el)
}
}
/**
* example
* v-role-permission="'role'" - single roles
* v-role-permission="'role'|'role1'" - multi roles
* v-role-permission="['role','role1']" - multi roles
* v-role-permission:[`include`]="'role'" - full define
* v-role-permission:[`exclude`]="'role'" - except some roles
*/
export default {
inserted: function (el, binding) {
validateRole(el, binding)
},
updated: function (el, binding) {
validateRole(el, binding)
}
}
指令批量自动注册
这样在指定模块目录中,添加了自定义指令后,无需再额外写注册代码
const modulesFiles = require.context('./modules', true, /\.js$/)
// create module to map
const directives = modulesFiles.keys().reduce((directives, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
directives[moduleName] = value.default
return directives
}, {})
// auto register
export default {
install(Vue) {
Object.keys(directives).forEach((key) => {
Vue.directive(key, directives[key])
})
}
}
全局Vue使用
import directives from './directives'
Vue.use(directives)
指令使用
<!--传递数组-->
<el-button v-role-permission="['ROLE_CUST_MANAGER','ROLE_CUST_MANAGER1']">测试1</el-button>
<!--传递字符串-->
<button v-role-permission="'ROLE_BRANCH_DIRECTOR|ROLE_BRANCH_DIRECTOR'">测试2</button>