vue中同时使用 v-if 和 v-auth 冲突问题

790 阅读1分钟

问题背景

  1. 列表页面,通过状态搜索时,发现切换状态时,按钮权限失效。
  2. v-authel.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>

原因

  1. 指令执行顺序问题

    • v-if 是 Vue 的内置指令,优先级较高。当 v-if 的条件为 false 时,Vue 会直接跳过该元素的渲染,不会执行任何其他指令。
    • 自定义指令(如 v-auth)依赖于元素的渲染逻辑,如果 v-if 的条件为 falsev-auth 指令可能根本不会被触发。
  2. 生命周期钩子的限制

    • 在某些情况下,v-auth 的生命周期钩子(如 bindinserted)可能在 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>