问题背景
- 列表页面,通过状态搜索时,发现切换状态时,按钮权限失效。
v-auth中el.parentNode打印结果时null。
v-auth 实现代码示例
import Vue from 'vue';
Vue.directive('auth', {
inserted(el, binding, vnode) {
const { value } = binding; // 获取指令绑定的值(权限标识)
const userPermissions = vnode.context.$store.state.user.permissions; // 从 Vuex 中获取用户权限
// 判断权限
if (!userPermissions.includes(value)) {
el.parentNode.removeChild(el); // 如果用户没有权限,则移除该元素
}
}
});
<template>
<button v-if="row.disbled === 0" v-auth="['admin-disabled']">禁用</div>
<button v-if="row.disbled === 1" v-auth="['admin-enabled']">启用</div>
</template>
原因
-
指令执行顺序问题:
v-if是 Vue 的内置指令,优先级较高。当v-if的条件为false时,Vue 会直接跳过该元素的渲染,不会执行任何其他指令。- 自定义指令(如
v-auth)依赖于元素的渲染逻辑,如果v-if的条件为false,v-auth指令可能根本不会被触发。
-
生命周期钩子的限制:
- 在某些情况下,
v-auth的生命周期钩子(如bind或inserted)可能在v-if条件生效之前执行,导致校验逻辑无法正确应用。
- 在某些情况下,
解决方法
第一种:避免在同一个标签
将 v-auth 放在父级元素上,确保它先执行权限校验。如果权限校验失败,父级元素会被移除,子元素也不会渲染
<template>
<div v-auth="['admin-disabled']">
<button v-if="row.status === 0">禁用</button>
</div>
<div v-auth="['admin-enabled']">
<button v-if="row.status === 1">启用</button>
</div>
</template>
第二种:通过计算属性(方法)判断权限
<template>
<button v-if="isShowDisabled(row)">禁用</div>
<button v-if="isShowEnabled(row)">启用</div>
</template>
<script>
export default {
data(){
return {
permission: ['admin-disabled', 'admin-enabled'],
}
},
method: {
isShowDisabled(row){
return row.disbled === 0 && this.permission.includes('admin-disabled')
},
isShowEnabled(row){
return row.disbled === 1 && this.permission.includes('admin-enabled')
}
}
}
</script>
第三种:v-show
<template>
<button v-show="row.disbled === 0" v-auth="['admin-disabled']">禁用</div>
<button v-show="row.disbled === 1" v-auth="['admin-enabled']">启用</div>
</template>