【发布时间】:2018-03-08 01:25:22
【问题描述】:
我正在为 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
}
});
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;
}
}
<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>
每当值发生变化时,无论是从用户单击(使用v-on:click)还是从变量本身发生变化(使用watch.value),我都会制作我的组件,“更改!”一词在复选框旁边闪烁几次。一切正常,但是当我们使用“更改为菜单”按钮更改菜单并且checked0 和checked1 是不同的值时,就会出现问题。 “已更改”会闪烁,即使它不应该闪烁。
这显然是vue回收组件并将它们用于另一个变量造成的。由于变量的值与旧的不同,watch.value 被运行,在我们期望它不会发生时触发动画。
我做了一些研究,发现我可以给我所有不同的复选框vue keys 像这样:<checkbox v-model="checked1" key="thing1">checked1</checkbox>,但我想优雅地解决这个问题并允许 vue 回收它想要的任何东西。应该有一种方法可以检测该值是因为实际发生了变化还是因为回收而发生了变化。
所以我的问题是如何解决这个问题,或者我如何以不同的方式编写代码以避免它?
【问题讨论】:
标签: javascript vue.js vuejs2