我为vue创建了一个可重复使用的复选框组件,并且我遇到了由vue回收未使用组件引起的一个有趣问题。
最好看一个例子:
Vue.component("checkbox", {
template: `
<div>
<slot></slot>:
<input type="checkbox" v-model="checked" v-on:change="updateVModel"/>
<span>changed!</span>
</div>
`,
props: {
value: {
type: Boolean,
required: true
}
},
data(){
return {checked: this.value};
},
watch: {
value(val){
this.changeAnimation();
this.checked = val;
}
},
methods: {
changeAnimation(){
let $span = this.$el.querySelector("span");
$span.classList.remove("animate");
setTimeout(() => $span.classList.add("animate"), 50);
},
updateVModel(){
this.changeAnimation();//this line is redundant since watch.value runs anyway
this.$emit("input", this.checked);
}
}
});
new Vue({
el: "#menu",
data: {
menu: 0,
checked0: true,
checked1: false
}
});
&#13;
span{
transition: 1s;
opacity: 0;
}
span.animate{
animation: notice-me .3s ease-in-out 4 alternate
}
@keyframes notice-me{
0%{
opacity: 0;
}
100%{
opacity: 1;
}
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="menu">
<div v-if="menu == 0">
<button v-on:click="menu = 1">Go to menu 1</button>
<h3>Menu 0</h3>
<checkbox v-model="checked0">checked0</checkbox>
<checkbox v-model="checked0">checked0</checkbox>
</div>
<div v-else>
<button v-on:click="menu = 0">Go to menu 0</button>
<h3>Menu 1</h3>
<checkbox v-model="checked1">checked1</checkbox>
<checkbox v-model="checked1">checked1</checkbox>
</div>
</div>
&#13;
每当值发生变化时,无论是通过用户点击(使用v-on:click
)还是通过变量本身更改(使用watch.value
),单词&# 34;改&#34!;除了复选框之外几次闪烁。一切正常,但是当我们使用&#34;更改为菜单&#34;更改菜单时会出现问题。 button和checked0和checked1是不同的值。 &#34;变更&#34;即使它不应该闪烁,也会闪烁。
这显然是由vue回收组件并将它们用于另一个变量引起的。由于变量的值与旧值不同,因此运行watch.value
,当我们预期不会发生时触发动画。
我做了一些研究,发现我可以像<checkbox v-model="checked1" key="thing1">checked1</checkbox>
一样给出所有不同的复选框vue keys,但我想优雅地解决这个问题并允许vue回收它想要的任何东西。应该有一种方法可以检测值是否因为实际上或由于回收而发生了变化。
所以我的问题是如何解决这个问题,或者我如何以不同的方式编写代码以避免它?
答案 0 :(得分:1)
key应该与条件呈现(v-for
或v-if
)单位相关联。它应该受到关于该单元的任何独特之处的约束。在您的情况下,您可以使用menu
:
<div v-if="menu == 0" :key="menu">
<button v-on:click="menu = 1">Go to menu 1</button>
<h3>Menu 0</h3>
<checkbox v-model="checked0">checked0</checkbox>
<checkbox v-model="checked0">checked0</checkbox>
</div>
<div v-else :key="menu">
<button v-on:click="menu = 0">Go to menu 0</button>
<h3>Menu 1</h3>
<checkbox v-model="checked1">checked1</checkbox>
<checkbox v-model="checked1">checked1</checkbox>
</div>