VUE自定义指令-权限校验
使用场景:
web后台项目都会有权限控制,可以分为两类,分别为页面权限
及操作权限
。
页面权限
:是指当前账号是否可以看到
此页面;操作权限
:是指当前账号在此页面可以做哪些操作
。
很显然,账号必须先要能看到此页面,才能说在此页面能做的操作。如果连页面都看不到,具有的操作毫无意义,一般查看
操作就是页面的权限,只能分配了查看
操作的权限,才能在此页面进行其它操作。
本文章只探讨操作权限的解决方案,页面权限
后面再新建文章
。
账号权限控制分类:
账号权限控制主要分为账号具有的角色
及账号具有的权限标识
。
角色
: 一个账号可以绑定多个角色,例如user
、admin
、test
等,不同的角色拥有不同的权限标识权限标识
: 一个为有权限的操作,例如sys:user:select
、sys:user:add
分别表示可以对用户管理这个页面进行查看及新增操作。
前端可以根据这两个权限信息来校验
用户具有的页面权限
及操作权限
。
例如(权限标识控制)
一个用户管理页面,分别有查询、新增、修改、删除
四个操作,且新增、修改、删除分别对应一个操作按钮
,此4个操作分别对应的权限标识为sys:user:select
、sys:user:create
、sys:user:update
、sys:user:delete
。当登录的账号具有sys:user:select
权限标识时,才可以看到此页面,否则无法进入此页面。
当用户具有
sys:user:create
权限标识时,才能看到(或者启用)
新增按钮,实现新增操作。否则此按钮隐藏(或者禁用)
。当用户具有
sys:user:update
权限标识时,才能看到(或者启用)
更新按钮,实现更新操作。否则此按钮隐藏(或者禁用)
。当用户具有
sys:user:delete
权限标识时,才能看到(或者启用)
删除按钮,实现删除操作。否则此按钮隐藏(或者禁用)
。
这样同一个管理后台,不同权限的账号
登录进来看到的效果及其操作都是不一样的
。
角色控制
也是相同的原理
。比如user
角色具有查看
及更新
的权限,admin
具有全部的操作权限
。
复杂场景
一个操作,需要多个接口才能完成。还是以用户管理举例,例如搜索条件有部门的下拉框,而下拉框
中的数据
是通过调用接口
来得到的。那么查询
这个操作,除了sys:user:select
权限标识外,还需要sys:org:list
权限标识。新增
操作也是如此,新增用户的时候也需要选择部门信息,那么除了sys:user:create
权限标识外还需要其它权限标识才能完整的实现操作。
总结:
权限标识
一般和后台接口
绑定,一个权限标识对应一个接口- 一个
操作
可能需要多个接口
才能完成功能
前端操作权限的本质
对于前端而言,操作权限的本质就是校验账号的具有的角色
或者权限标识
是否具有此按钮(或者dom)需要的角色或者权限标识
,通过这个校验的结果来控制删除/禁用按钮(或者dom)
或者显示/启用按钮(或者dom)
。
例子
例如有一个新增的按钮,需要有sys:user:create
权限标识才能看到此按钮,伪代码如下
if(isPerms('sys:user:create')){<!-- 有权限,显示按钮 --><button>新增用户</button>}else{<!-- 没有权限不显示按钮 -->}
从上面的结果来看,需要我们收到的操作dom元素,实现对dom的显示/隐藏或者启用/禁用。
解决方案
用vuex存储用户的所有角色及权限标识,并封装成判断的方法,VUE实例上挂载全局属性方法,方便所有组件调用,同时封装自定义指令,指令中的判断逻辑也是调用此判断方法。
权限校验工具方法
permissionUtils.js
/*** 权限校验工具*/
import store from "@/store";/*** 权限校验的类型* @type {{ROLE: string, PERMS: string}}*/
export const PermTypeEnum = {PERMS: 'perms',ROLE: 'role'
}/*** 权限校验的操作* @type {{OR: string, AND: string}}*/
export const CheckOperateEnum = {AND: 'and',OR: 'or'
}/*** 检查是否具有全部资源权限* @param checkPerms {Array<String>} 检查的资源* @param allPerms {Array<String>} 具有的资源* @returns {Boolean} true 具有权限 false 没有权限*/
export const checkPermsAll = (checkPerms, allPerms) => (checkPerms || []).every((perm) => allPerms.includes(perm))/*** 检查是否具有任意资源权限* @param checkPerms {Array<String>} 检查的资源* @param allPerms {Array<String>} 具有的资源* @returns {Boolean} true 具有权限 false 没有权限*/
export const checkPermsAny = (checkPerms, allPerms) => (checkPerms || []).some((perm) => allPerms.includes(perm))/*** 权限校验* @param checkPerms {String|Array} 需要检查的权限* @param permType 权限的类型,角色或者权限标识* @param checkOperate 操作类型,且或者 是 或* @returns {Boolean} 是否具有权限, true 有权限, false 无权限*/
export const checkPermissions = (checkPerms,permType = PermTypeEnum.PERMS,checkOperate = CheckOperateEnum.AND) => {//得到用户具有的权限集合const perms = store.getters.perms// 得到用户具有的角色集合const roles = store.getters.roles.map(role => role.roleId)//权限判断结果const allPerms = []//开始判断是 角色权限校验 还是 权限校验 , 再判断是 或 操作 还是 与 操作if (permType === PermTypeEnum.ROLE) {allPerms.push(...roles)} else {allPerms.push(...perms)}//这里需要对校验的权限标记或者角色进行转换为数组const needCheckPerms = []if (checkPerms) {if ((checkPerms instanceof Array) && (checkPerms.length > 0)) {//如果输入数据为数组,则直接加入needCheckPerms.push(...checkPerms)} else if ((typeof checkPerms) === 'string') {needCheckPerms.push(checkPerms)}}let hasPerm = false;// 如果包含特殊标识,则视为管理员,全部放行if (allPerms.includes('*')) {hasPerm = true;} else {// 判断是 或 操作 还是 与 操作 , 如果给了or的修饰符,则表示为任意权限if (checkOperate === CheckOperateEnum.OR) {hasPerm = checkPermsAny(needCheckPerms, allPerms)} else {hasPerm = checkPermsAll(needCheckPerms, allPerms)}}return hasPerm;
}export default {PermTypeEnum,CheckOperateEnum,checkPermissions
}
挂载到全局属性
这里可以想到vue提供的v-if指令,再结合全局方法属性配合实现,在全局方法属性中提供权限校验,用v-if指令来实现操作dom。
例子如下:
import {checkPermissions} from "@/utils/permissionUtils";
/*** 挂载全局 权限判断函数*/
Vue.prototype.isPerms = checkPermissions
使用
<button v-if="isPerms(['sys:user:create','sys:org:list'])">新增用户</button>
此方案可以实现,但过于单一,不过灵活。如果需要扩展角色权限校验或者采用任意权限无法很好的扩展。
自定义权限指令 (推荐)
注册vue的自定义指令,在自定义指令的钩子函数中提供绑定的参数及其dom,这样就可以进行dom操作。在自定义指令中dom元素挂载在父dom后,进行权限校验,如果权限不满足,则删除此dom
。
自定义指令代码如下:
import {CheckOperateEnum, checkPermissions, PermTypeEnum} from '@/utils/permissionUtils'/*** 权限校验命令,支持:* * 角色权限校验* * 权限标识校验* * 输入为字符串或者数组* * 任意权限或者全部权限校验* 使用例子 :* 权限标识校验:* 全部存在 v-permission="['sys:user:create','sys:user:list']" 或者 v-permission="'sys:user:create'"* 任意存在 v-permission.or="['sys:user:create','sys:user:list']"** 角色权限校验:* 全部存在 v-permission:role="['user1','user2']" 或者 v-permission="'user'"* 任意任意 v-permission:role.or="['user1','user2']"**/
export default {//被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)/*el:指令所绑定的元素,可以用来直接操作 DOM。binding:一个对象,包含以下 property:name:指令名,不包括 v- 前缀。value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。*/inserted(el, binding, vnode) {// 得到指令的绑定值,此值为js计算完成后的值,当前为需要的权限const {value, arg, modifiers} = bindingif (value) {//权限判断结果 , 这里会处理字符串及数组的情况const hasPermission = checkPermissions(value,(arg === 'role') ? PermTypeEnum.ROLE : PermTypeEnum.PERMS,modifiers.or ? CheckOperateEnum.OR : CheckOperateEnum.AND)if (!hasPermission) {//如果没有权限则直接删除此节点el.parentNode && el.parentNode.removeChild(el)}} else {throw new Error(`缺少权限标识 例如 v-permission="['sys:user:create','sys:user:list']" 或者 v-permission:role="['user']" `)}}
}
挂载指令
Vue.directive('permission', permission)
使用例子
<div v-permission:role.or="['admin','role']"><span>admin和role角色都能看到我</span></div><div v-permission:role="['admin','user']"><span>必须同时有admin和user角色才能看到</span></div><div v-permission="['sys:user:select','sys:org:list']"><span>必须同时有sys:user:select和sys:org:list权限标识才能看到</span></div><div v-permission.or="['sys:user:select','sys:org:list']"><span>sys:user:select和sys:org:list权限标识都能看到我</span></div>
VUE自定义指令-权限校验相关推荐
- vue 自定义指令 权限指令
目前项目中需要做到按钮级别的控制,所以想到了自定义指令来实现,在自定义指令中来控制组件的显示于隐藏. 1.第一步创建自定义指令 js 文件: permission.js 2.在main.js中直接引入 ...
- clientsideevents能定义几个click事件_分享8个非常实用的Vue自定义指令
作者:lzg9527 https://juejin.cn/post/6906028995133833230 在 Vue,除了核心功能默认内置的指令 ( v-model 和 v-show ),Vue 也 ...
- Vue自定义指令介绍及原理
Vue自定义指令 Vue指令: 在使用Vue框架进行前端开发时,我们经常会使用一些特殊指令来快速实现一些效果或功能. 常见指令如:v-bind.v-if (v-else).v-show.v-html等 ...
- vue自定义指令封装节流_Vue自定义指令封装节流函数的方法示例
节流函数是web前端开发中经常用到的一个开发技巧,在input实时搜索,滚动事件等,为了避免过多消耗性能,我们都会使用节流函数.在<JavaScript高级程序设计>一书中有这样的一个例子 ...
- vuejs 指令封装 button 加载效果_这些Vue自定义指令,让你的项目开发爽到爆
受 AngularJS 的启发,Vue 内置了一些非常有用的指令(比如v-html 和 v-once等),每个指令都有自身的用途.完整的指令列表可以在这里查看. 这还没完,更棒的是可以开发自定义指令. ...
- vue 自定义指令(directive)实例
一.内置指令 1.v-bind:响应并更新DOM特性:例如:v-bind:href v-bind:class v-bind:title v-bind:bb 2.v-on:用于监听DOM事件: 例 ...
- pyqt5 treeview鼠标右键菜单事件_【动手实践】使用 Vue 自定义指令实现右键菜单...
本文来自于 神奇的程序员 前言 浏览器里右键时会有一个默认的菜单,在我的开源项目中正好有自定义右键菜单的需求,在npm库找了下与之相关的包,发现都是以组件形式实现的,感觉那种做法太过繁琐. 于是,我就 ...
- html标签outclick,vue自定义指令(Directive中的clickoutside.js)的理解
阅读目录 vue自定义指令clickoutside.js的理解 vue自定义指令请看如下博客: 一般在需要 DOM 操作时我们都需要使用自定义指令的方式去实现,当然一些特殊的事件监听也可以使用指令,例 ...
- 9、Vue自定义指令
Vue自定义指令 1.vue指令和自定义指令 2.使用自定义指令 2.1.全局注册 2.2.局部注册 3.钩子函数 1.vue指令和自定义指令 什么是指令? v-model.v-bind.v-on.v ...
最新文章
- LeetCode 3Sum
- Android中Intent的显示和隐式使用
- Android之让代码跑在主线程(无context上下文)的封装
- 云架构师是做什么的_为什么以及如何成为云架构师
- string与string.h的区别
- SpringBoot指南(三)——静态资源、欢迎页、Favicon、默认页面
- 为什么我会弃Java,选择了Kotlin——专访《Java编程思想》作者 Bruce Eckel
- CSS基础——CSS 列表和表单【学习笔记】
- dumpsys gfxinfo packacges计算帧率
- pandas中read_csv的缺失值处理
- Gerald and Giant Chess
- ASP.NET2.0 ReportingServices,报表灵魂的收割者(一)【月儿原创】
- HttpEntity的类型及其使用(各种继承的使用)
- oracle 抽样_利用ORACLE实现数据抽样(sample block)
- Python Flask Web 框架入门
- PTA 7-47 打印选课学生名单分数 25 分 (C 邻接表+二叉排序树 )
- 用docker跑机器学习环境
- 什么是重绘,重排?如何解决?
- Microsoft Office Word使用技巧(各种报告论文排版可能需要的小技巧)
- 股权控制权的五种设计策略