同时使用v-if和v-directive删除元素会导致渲染异常

同时使用v-if和v-directive删除元素会导致渲染异常

在多个并列的元素上使用自定义指令删除元素,并且切换元素的 v-if 值时会导致渲染异常。

Vue.directive("permission", {

inserted: function (el, info, vnode) {

if (!whiteList.includes(info.arg)) {

el.parentNode && el.parentNode.removeChild(el);

}

}

});

比方说现在有三个按钮同时需要条件渲染和权限控制。

按钮是否有权限切换前的v-if值切换后的v-if值
button1falsetrue
button2truetrue
button3truefalse

按照上面的表中的逻辑,初始化应该显示 button2,切换后应该显示 button1 和 button2。
但是实际情况是初始化渲染正常,切换后只显示了 button1,button2不见了。

目前找到的方案是不要将这些按钮放在同一层级下。

但是我感觉是因为上面自定义指令的问题,因为在自定义指令中删除了元素,但是vue本身并不知道这个变化,vnode中的elm会引用这个删除的dom节点,导致在做diff的时候出错了。

想问下能不能只修改自定义指令的实现,不去修改template?

这里提供了这个缺陷的复现地址

相关的代码如下:

// APP.vue

<template>

<div id="app">

<div>

<a-button v-permission:btn1 v-if="showBtn1" type="primary">Button1</a-button>

<a-button v-permission:btn2 v-if="showBtn2" type="primary">Button2</a-button>

<a-button v-permission:btn3 v-if="showBtn3" type="primary">Button3</a-button>

</div>

<br />

<button @click="onClick">Click me</button>

</div>

</template>

<script>

export default {

name: "App",

data() {

return {

showBtn1: false,

showBtn2: true,

showBtn3: true,

};

},

methods: {

onClick() {

this.showBtn1 = !this.showBtn1;

this.showBtn3 = !this.showBtn3;

},

},

};

</script>

// main.js

import Vue from "vue";

import App from "./App.vue";

const whiteList = ["btn1", "btn2"];

Vue.directive("permission", {

inserted: function (el, info, vnode) {

if (!whiteList.includes(info.arg)) {

(el.parentNode && el.parentNode.removeChild(el)) ||

(el.style.display = "none");

}

}

});

new Vue({

render: (h) => h(App)

}).$mount("#app");


回答:

根据你的描述,v-permission 和 v-if 确实最好不要作用在同一个元素上,会使元素状态变化非常混乱不可预测。
我觉得还是修改 template 会合理一些。

// v-if 可以改成 v-show (不排除其它代码会和 v-permission 里关于 display=none 的处理有冲突)

<button v-permission:btn1 v-show="showBtn1" type="button">Button1</button>

// 或者 a-button 外面再包一层 div 处理 permission

<div v-permission:btn1>

<a-button v-if="showBtn1" type="primary">Button1</a-button>

</div>

以上是 同时使用v-if和v-directive删除元素会导致渲染异常 的全部内容, 来源链接: utcz.com/p/936924.html

回到顶部