请运行工作演示:
let myCheckbox = Vue.component('my-checkbox', {
template: `<div>
<input type="checkbox" id="check1" :checked="checked" @change="change">{{checked}}
</div>`,
props: ['checked'],
methods: {
change() {
this.$emit('change', event.target.checked);
}
}
})
new Vue({
el: '#app',
data: {
checked: true,
count: 1
},
methods: {
change(isChecked) {
this.count++
this.checked = isChecked
if (this.count % 2 === 0) {
// this.checked = !isChecked
setTimeout(() => {
this.checked = !isChecked
}, 10);
}
}
},
components: {
myCheckbox
}
})
&#13;
span {
background: pink;
}
&#13;
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<my-checkbox :checked="checked" @change="change"></my-checkbox>
When
<span>{{count}}</span> is even your check will fail
</div>
&#13;
但是,如果我将同步操作更改为change
中的异步操作,这意味着更改
setTimeout(() => {
this.checked = !isChecked
}, 10);
到
this.checked = !isChecked
该演示无法正常运行,因为checked
中的check1
未更新。
我的问题是
我不知道为什么同步操作不起作用!
我想在promise
之后有一个change
进行基础操作,这就是为什么setTimeout
有效。但是,我不确定,我没有&#39}找不到任何解释。
答案 0 :(得分:2)
当勾选复选框时,(原生DOM)复选框会通过添加v
(刻度符号)来更改其外观。
当该滴答发生时,它会发出change
事件。
请注意,此时,Vue的checked
属性尚未更改。当“某人”选择change
事件并相应地设置checked
时,就会发生此更改。这就是下面的第4行:
methods: { // 1
change(isChecked) { // 2
this.count++; // 3
this.checked = isChecked // 4
现在,当this.count
为偶数时,在代码没有 setTimeout
的情况下,您立即将this.checked
设置为其之前的值。
因此,由于Vue发现this.checked
在执行方法后没有改变,因此Vue知道没有更新(没有重新绘制)。这就是为什么勾选的符号(上面v
)仍然(错误地)勾选:Vue没有重新绘制该组件。
作为证明,请尝试下面的演示。请注意,updated
生命周期处理程序永远不会执行:
let myCheckbox = Vue.component('my-checkbox', {
template:
`<div>
<input type="checkbox" id="check1" :checked="checked" @change="change">{{checked}}
</div>`,
props: ['checked'],
methods: {
change() {
this.$emit('change', event.target.checked);
}
},
// not executed because `checked` never changes (is always true)
updated() { console.log('my-checkbox updated') }
})
new Vue({
el: '#app',
data: {
checked: true,
count: 1
},
methods: {
change(isChecked) {
this.count++;
this.checked = isChecked
if (this.count % 2 === 0) {
this.checked = !isChecked
}
}
},
components: {
myCheckbox
}
})
span {
background: pink;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<my-checkbox :checked="checked" @change="change"></my-checkbox>
When
<span>{{count}}</span> is even your check will fail. - checked: <span>{{checked}}</span> - it never changes, always <b>true</b>, so my-checkbox <b>never</b> has to be updated/repainted.
</div>
现在,当您使用setTimeout
时,change(isChecked)
方法已结束执行,this.checked
已更改!这会引发重画。
问题是在setTimeout
处理程序执行后不久,将this.checked
恢复为原始值。这会触发另一次重绘。请注意,在下面的演示中,当this.count
为偶数时,更新的挂钩执行两次。
最后,作为最后一点,在Vue中这样做的惯用方法是using Vue.nextTick()
,而不是setTimeout
:
let myCheckbox = Vue.component('my-checkbox', {
template:
`<div>
<input type="checkbox" id="check1" :checked="checked" @change="change">{{checked}}
</div>`,
props: ['checked'],
methods: {
change() {
this.$emit('change', event.target.checked);
}
},
updated() { console.log('my-checkbox updated') },
})
new Vue({
el: '#app',
data: {
checked: true,
count: 1
},
methods: {
change(isChecked) {
this.count++;
this.checked = isChecked
if (this.count % 2 === 0) {
Vue.nextTick(() => {
this.checked = !isChecked
});
//setTimeout(() => {
// this.checked = !isChecked
//}, 10);
}
}
},
components: {
myCheckbox
}
})
span {
background: pink;
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<my-checkbox :checked="checked" @change="change"></my-checkbox>
When
<span>{{count}}</span> is even the checked will be overridden. checked: <span>{{checked}}</span>
</div>