vue自定义指令与v-if结合的按钮级别权限控制

4 篇文章 0 订阅

需求描述:按钮 根据 “角色” 显示或隐藏。同时该按钮也可以有其他展示条件。
如:按钮 “开启彩虹桥”显示条件是,当账户角色为 Asgard 或 Avenger,且页面中存在 Bifrost。
注意点:

  • 页面刚进入时,不展示按钮
  • v-if
  • 可以有多个角色

期望最终使用方式


<button
	v-if="Bifrost"
	v-btnPermit="roles"
>
	开启彩虹桥
</button>

// 也可以只判断角色
<button
	v-btnPermit="roles"
>
	开启彩虹桥
</button>
// -----
{
	roles: ['Asgard','Avenger'], // string|string[] 可以使用该按钮的角色列表
	Bifrost: true // Boolean
}

遇到的问题与解决思路

我写的也迷糊=_=,你们大概看看,不对的地方请指正。
在这里插入图片描述

  • 通过接口获取当前账户的角色,并存储到vuex中。
  • 每次项目初始化(刷新)时调用 GetRoles,防止角色被更新后页面逻辑不能及时更新。我放在了最外层的layout页面。
  • 接口是异步进行的,会出现符合展示条件时,按钮并未展示或隐藏的问题。需要同步处理,等接口执行完毕再判断展示的逻辑
  • 上面的处理按照正常登录进入系统的逻辑是没问题的。如果在有权限类按钮页面做了刷新,但此时还没获取到角色列表,自定义指令的钩子中,会去调用接口并等待处理。这个逻辑就会有一种问题:页面有10个权限类的按钮,会同时调用10次接口,有好的解决方案的朋友们,可以留言说一下
  • 角色权重大于if条件。如果角色不存在,直接移除节点。
  • 默认先用样式控制隐藏 display:none。页面默认不展示有权限控制的节点。
  • 使用inserted,主要是因为做了同步处理一步到位了。如果if条件发生更改,也会触发inserted

代码

// vuex

state: {
	allRoles: null
}
mutations: {
	SET_ROLE: (state, roles) => {
		state.allRoles = roles
	}
}
actions: {
	GetRoles({commit}) {
		return new Promise((resolve) => {
			// axios 请求接口,并处理成数据 resolve([角色列表])
			// 注意接口错误时,返回 空数组 []
		})
	}
}
Vue.directive('btnPermit', {
	inserted: async(el, binding)=> {
		el.style.display = 'none'
		/**
		* 判断该账户下的角色列表中是否包含
		* role string[] | string
		* list string[]
		*/
		const passRole = (role, list) => {
			if(!list) return false // 没有获取到角色
			if(role instanceof Array) {
				return role.some(item => list.includes(item))
			} else {
				return list.includes(role)
			}
		}
		const _roles = binding.value
		
		if(!store.getters.allRoles) {
			// _res 等待接口获取到该账户的所有角色,再进行处理
			const _res = await store.dispatch('GetRoles')
			if(!passRole(_roles, _res)) {
				el.parentNode ? el.parentNode.removeChild(el) : el.remove()
			} else {
				el.style.display = 'unset' // 考虑到影响原有布局问题,block 改为 unset了
			}
		} else {
			if(!passRole(_roles, _res)) {
				el.parentNode ? el.parentNode.removeChild(el) : el.remove()
			} else {
				el.style.display = 'unset'
			}
		}
	}
})

补充

不用v-show是在想,如果他没这个权限,页面中还有节点,那有懂代码的手动给我block了咋整。在这里插入图片描述

v-show场景的思路,仅供参考,欢迎提供方案

如果你们有v-show的需求,我之前的思路是,可以把条件的值传入自定义指令,在update函数中处理逻辑。比如:isShow=true
<button v-show="isShow" v-btnPermit:show="{ roles: ['Loki'], show: isShow }">
根据 binding.arg 判断是否有 show 条件,
binding.value 这时是 { roles: ['Loki'], show: true }
可以取到 v-show此时的值,结合passRole的判断角色存在不,处理下 el.style.display

我傻了

好不容易折腾完了这个功能,然后又吭哧写了博客,刚才突然想到:为啥我不直接在最外层加个div啥的,直接给个v-if 或者v-show…
想下班了… 我决定不改了.如果有帮助到你们,我很开心,没帮到的话,,,反正你也看到这里了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3中,可以通过自定义指令来实现按钮权限控制。下面是一个简单的示例: 首先,创建一个自定义指令文件(例如`permission.js`): ```javascript import { Directive } from 'vue'; const permissionDirective: Directive = { mounted(el, binding) { const { value } = binding; // 根据用户的权限进行判断 if (!checkPermission(value)) { el.style.display = 'none'; } }, }; export default permissionDirective; ``` 在上述代码中,我们定义了一个`permissionDirective`指令,在`mounted`钩子函数中根据用户的权限(这里使用`checkPermission`函数作为示例)来判断是否显示按钮。如果权限不满足条件,则将按钮的`display`属性设置为`none`,从而隐藏按钮。 接下来,在Vue组件中使用自定义指令: ```vue <template> <button v-permission="'button.permission'">按钮</button> </template> <script> import { defineComponent } from 'vue'; import permissionDirective from './permission'; export default defineComponent({ directives: { permission: permissionDirective, }, }); </script> ``` 在上述代码中,我们通过`v-permission`指令绑定了一个权限值(例如`'button.permission'`)。当组件渲染时,自定义指令会根据权限值进行判断,并控制按钮的显隐。 需要注意的是,上述代码中的`checkPermission`函数需要根据实际业务逻辑进行实现,用于判断用户是否具有相应的权限。 这是一个简单的示例,你可以根据自己的需求进行修改和扩展以满足具体的按钮权限控制需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值