单击复选框后,V模型未更新

时间:2018-07-19 18:59:45

标签: vue.js

任何想法如何解决此问题:

在此example中,作者使用的vue 2.3.2完美无缺,

new Vue({
  el: '#app',
  data: {
    users: [{
        "id": "Shad",
        "name": "Shad"
      },
      {
        "id": "Duane",
        "name": "Duane"
      },
      {
        "id": "Myah",
        "name": "Myah"
      },
      {
        "id": "Kamron",
        "name": "Kamron"
      },
      {
        "id": "Brendon",
        "name": "Brendon"
      }
    ],
    selected: [],
    allSelected: false,
    userIds: []
  },
  methods: {
    selectAll: function() {
      this.userIds = [];

      if (this.allSelected) {
        for (user in this.users) {
          this.userIds.push(this.users[user].id.toString());
        }
      }
    },
    select: function() {
      this.allSelected = false;
    }
  }
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
  <h4>User</h4>
  <div>
    <table>
      <tr>
        <th>Name</th>
        <th>Select All<input type="checkbox" @click="selectAll" v-model="allSelected"></th>
      </tr>
      <tr v-for="user in users">
        <td>{{ user.name }}</td>
        <td><input type="checkbox" v-model="userIds" @click="select" :value="user.id"></td>
      </tr>
    </table>
  </div>

  <span>Selected Ids: {{ userIds }}</span>
</div>

当我将其切换为2.5.16( <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> )时,该行为很奇怪:

点击selectAll复选框时,只有该复选框处于选中状态,但是当我将其切换为取消选中状态时,下面的所有复选框都被选中了

enter image description here

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:6)

为了获得一致的浏览器功能,我建议不使用单击/更改复选框。而是将复选框绑定到一个值(您已经完成),然后在该值上使用观察程序。这样,复选框的实际值将始终准确地表示其状态。所以你会有这样的东西:

<input type="checkbox" v-model="allSelected">


Vue.component({..., {
    data: function() {
             return {
                allSelected: false,
             }
          }
    },
    watch: {
        allSelected: function(val){
            //Use your source of truth to trigger events!
            this.doThingWithRealValue(val); 
        }
    }
});

您已经将allSelected的组件数据值用作事实来源,因此您应使用此事实来源作为实际触发元素值,而不是单击。只要allSelected的值发生变化,您的代码就会被执行。这样就解决了渲染顺序怪异的问题。

答案 1 :(得分:4)

正如rob在评论中和他的回答中所指出的那样,您不能依靠@click / @input / @change在所有浏览器中在执行顺序方面具有相同的行为相对于实际模型的更改。 VueJS存储库中存在一个上下文更多的问题:teach 'contrib/git-jump/git-jump' how to seek to the first matching position of a grep match in your editor

更好的解决方案是观察模型的变化,然后做出相应的反应。

new Vue({
  el: '#app',
  data: {
    users: [{
        "id": "Shad",
        "name": "Shad"
      },
      {
        "id": "Duane",
        "name": "Duane"
      },
      {
        "id": "Myah",
        "name": "Myah"
      },
      {
        "id": "Kamron",
        "name": "Kamron"
      },
      {
        "id": "Brendon",
        "name": "Brendon"
      }
    ],
    selected: [],
    allSelected: false,
    userIds: []
  },
  methods: {
    selectAll: function() {
      this.userIds = [];

      if (this.allSelected) {
        for (user in this.users) {
          this.userIds.push(this.users[user].id.toString());
        }
      }
    },
    select: function() {
      this.allSelected = false;
    }
  },
  watch: {
      allSelected: function () {
          this.selectAll()
      }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

<div id="app">
  <h4>User</h4>
  <div>
    <table>
      <tr>
        <th>Name</th>
        <th>Select All<input type="checkbox" v-model="allSelected"></th>
      </tr>
      <tr v-for="user in users">
        <td>{{ user.name }}</td>
        <td><input type="checkbox" v-model="userIds" @click="select" :value="user.id"></td>
      </tr>
    </table>
  </div>

  <span>Selected Ids: {{ userIds }}</span>
</div>