同时使用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值 |
---|---|---|---|
button1 | 是 | false | true |
button2 | 是 | true | true |
button3 | 否 | true | false |
按照上面的表中的逻辑,初始化应该显示 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.jsimport 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