在 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 渲染机制。

检查这个:

  1. 只选中了最后一个复选框,因此模型值为 ['krw']
  2. 取消选中最后一个复选框
  3. Watcher 已执行 - 新模型值为 [] 但 watcher 立即将其设置为 与之前相同的值 ... ['krw']
  4. 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>