在 watch 函数中更改数据时,dom 不会更新
When data is changed within the watch function, dom does not update
下面是一个组件中的数据
data: function () {
return {
sltAreaStyle: {
paddingTop: "3%",
},
checkedTypes: ["krw", "btc", "usdt"],
};
},
下面是checkedTypes数据的watch函数
watch: {
checkedTypes: {
handler: function (newVal, oldVal) {
if (newVal.length < 1) {
alert("Choose one or more.");
var last = oldVal[0];
this.$data.checkedTypes = [last];
}
},
},
},
下面是我的html模板
<div class="ckbxArea">
<input type="checkbox" value="krw" v-model="checkedTypes">KRW</input>
<input type="checkbox" value="btc" v-model="checkedTypes">BTC</input>
<input type="checkbox" value="usdt" v-model="checkedTypes">USDT</input>
</div>
我想在取消选中所有复选框时将最后一个值更改为 checkedTypes
数据。
如果最终取消选中第一个复选框,则 checkedTypes
将是 'krw' 就像 checkedTypes = ['krw']
checkedTypes
数据是 ['krw']
,但所有复选框标记都未选中。也就是dom还没有更新。我觉得我不太了解Vue的生命周期。我觉得这个问题跟v-model和components的生命周期有关,但是不知道是什么问题。请解释为什么会出现这个问题,并告诉我如何解决。
嗯,这更多是关于 v-model
字段输入控件的 Vue 渲染机制。
检查这个:
- 只选中了最后一个复选框,因此模型值为
['krw']
- 取消选中最后一个复选框
- Watcher 已执行 - 新模型值为
[]
但 watcher 立即将其设置为 与之前相同的值 ... ['krw']
- Vue 重新渲染模板(查看控制台中的消息)但是因为
v-model
值与上次渲染期间的值相同,它不会更新复选框
这种情况的简单解决方案是使用 nextTick
将更新推迟到下一个渲染周期
this.$nextTick(() => {
this.checkedTypes = [last];
})
new Vue({
el: "#app",
data: function () {
return {
checkedTypes: ["krw", "btc", "usdt"],
};
},
updated() {
console.log("Component updated")
},
watch: {
checkedTypes: {
handler: function (newVal, oldVal) {
if (newVal.length < 1) {
alert("Choose one or more.");
//console.log("Choose one or more.");
var last = oldVal[0];
// this.checkedTypes = [last];
this.$nextTick(() => {
this.checkedTypes = [last];
})
}
},
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id="app">
<input type="checkbox" value="krw" v-model="checkedTypes"/> KRW
<input type="checkbox" value="btc" v-model="checkedTypes"/> BTC
<input type="checkbox" value="usdt" v-model="checkedTypes"/> USDT
<pre>{{ checkedTypes }}</pre>
</div>
下面是一个组件中的数据
data: function () {
return {
sltAreaStyle: {
paddingTop: "3%",
},
checkedTypes: ["krw", "btc", "usdt"],
};
},
下面是checkedTypes数据的watch函数
watch: {
checkedTypes: {
handler: function (newVal, oldVal) {
if (newVal.length < 1) {
alert("Choose one or more.");
var last = oldVal[0];
this.$data.checkedTypes = [last];
}
},
},
},
下面是我的html模板
<div class="ckbxArea">
<input type="checkbox" value="krw" v-model="checkedTypes">KRW</input>
<input type="checkbox" value="btc" v-model="checkedTypes">BTC</input>
<input type="checkbox" value="usdt" v-model="checkedTypes">USDT</input>
</div>
我想在取消选中所有复选框时将最后一个值更改为 checkedTypes
数据。
如果最终取消选中第一个复选框,则 checkedTypes
将是 'krw' 就像 checkedTypes = ['krw']
checkedTypes
数据是 ['krw']
,但所有复选框标记都未选中。也就是dom还没有更新。我觉得我不太了解Vue的生命周期。我觉得这个问题跟v-model和components的生命周期有关,但是不知道是什么问题。请解释为什么会出现这个问题,并告诉我如何解决。
嗯,这更多是关于 v-model
字段输入控件的 Vue 渲染机制。
检查这个:
- 只选中了最后一个复选框,因此模型值为
['krw']
- 取消选中最后一个复选框
- Watcher 已执行 - 新模型值为
[]
但 watcher 立即将其设置为 与之前相同的值 ...['krw']
- Vue 重新渲染模板(查看控制台中的消息)但是因为
v-model
值与上次渲染期间的值相同,它不会更新复选框
这种情况的简单解决方案是使用 nextTick
将更新推迟到下一个渲染周期this.$nextTick(() => {
this.checkedTypes = [last];
})
new Vue({
el: "#app",
data: function () {
return {
checkedTypes: ["krw", "btc", "usdt"],
};
},
updated() {
console.log("Component updated")
},
watch: {
checkedTypes: {
handler: function (newVal, oldVal) {
if (newVal.length < 1) {
alert("Choose one or more.");
//console.log("Choose one or more.");
var last = oldVal[0];
// this.checkedTypes = [last];
this.$nextTick(() => {
this.checkedTypes = [last];
})
}
},
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<div id="app">
<input type="checkbox" value="krw" v-model="checkedTypes"/> KRW
<input type="checkbox" value="btc" v-model="checkedTypes"/> BTC
<input type="checkbox" value="usdt" v-model="checkedTypes"/> USDT
<pre>{{ checkedTypes }}</pre>
</div>