数组中对象的属性在所有元素都更改时是反应性的,但如果只有一些元素更改则不是

Posted

技术标签:

【中文标题】数组中对象的属性在所有元素都更改时是反应性的,但如果只有一些元素更改则不是【英文标题】:Property of object in array is reactive when all elements are changed, but not if only some are changed 【发布时间】:2021-02-06 02:50:50 【问题描述】:

我有这个 selectAllToggle 函数,它反应性地选择或取消选择数组中的所有元素。响应式,当使用 selectButton 时,浏览器中的所有复选框都显示为选中或取消选中。

当手动选择一个或多个(但不是全部)复选框时会出现问题。如果选中任何复选框,则 selectButtonName 更改为“取消全选”,按下时,我希望它取消全选。 我正确更新了数组的代码,因为它将数组中的每个学生的“selected”属性设置为 false,但它的反应性不起作用 - 手动选择的学生的复选框保持勾选状态在浏览器中。

selectAllToggle: function(key, row, $event) 
    var setTo = false;
    var newname = "Select All";
    if (this.selectButtonName === "Select All") 
        setTo = true;
        newname = "Deselect All";
    
    if (this.selectButtonName === "Deselect All") 
        setTo = false;
        newname = "Select All";
    

    if (this.students.length > 0) 
        for (var i = 0; i < this.students.length; i++) 
            this.students[i]['selected'] = setTo;
        
    
    this.selectButtonName = newname;
    
    console.log(this.students);    //shows the correct 'selected' state for all
,

视图看起来像这样(使用 vue-tables-2)

<v-client-table 
   v-if="gridReady" 
   v-model.sync="students" 
   :columns="gridcolumns" 
   :options="gridoptions"
   ref="grid">

<input type="checkbox" 
    slot="selected" 
    slot-scope="row, update" 
    v-model="row.selected"
    @change="selectStudent('select', row, $event)">

</v-client-table>

我可以做些什么来使这个函数反应?

【问题讨论】:

也许 Vue 没有观察到学生对象。您如何加载学生数据?它是否在 data 属性中预先声明?每个学生对象是否有一个selected 属性您将其分配给数据(好)还是您稍后添加这些属性(坏)? 学生数据在 data 属性中预先声明,但从后端加载时没有 selected 属性 - 它是在 vue js 中添加的。我可以在后端添加这个属性 - 似乎是一个很好的建议,所以会在这里评论它是否有效 @DecadeMoon 我现在为从后端加载的每个学生选择了 = false,但仍然存在同样的问题。但这不是你建议的我想的那样。因为事情的顺序(据我所知)是:数据属性>挂载> refreshGrid(从后端加载学生数据)。我能想到的从一开始就将它放在 data 属性中的唯一方法是,如果学生作为道具进来,然后在数据中我有 localStudents: this.students。 后端不应该使用selected 属性污染学生对象,这是一个仅限前端的属性。您只需按顺序执行 (1) 获取学生数据,(2) 遍历每个学生并添加 selected 属性,(3) 将学生数组分配给 this。否则你需要使用Vue.set。 @DecadeMoon 我之前试过 Vue.set,可能用错了。现在我让它工作了,但是解决它的方法是在 selectStudent 函数中也使用 Vue.set,这是一次选择一个学生时使用的。谢谢 - 你的知识真的帮助了我。如果您将您的 cmets 添加为一个,我已准备好接受答案。 【参考方案1】:

对于在一个或多个元素选择后取消选择,您可以使用computed property 作为下面的 sn-p 进行反应性执行。

new Vue(
  el: '#app',

  data: 
    selected: [],
    clientList: [1, 2, 3, 4, 5]

  ,
  computed: 
    selectAll: 
      get: function() 
        return this.selected.length > 0 &&
          this.selected.length <= this.clientList.length
      ,
      set: function(value) 
        let list = [];
        if (value) 
          this.selected = this.clientList
         else 
          this.selected = []
        

      
    
  ,
);
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">

  <title>Document</title>
</head>

<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.7/vue.js"></script>

  <div id='app'>
    <table id="example1" class="table table-bordered table-striped">
      <thead>
        <tr>
          <th>Client Name</th>
          <th style="width: 10%"><input type="checkbox" v-model="selectAll" /></th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(item,index) in clientList">
          <td style="font-weight: bold;width: 75%">item
          </td>
          <td style="width: 25%">
            <input type="checkbox" :value="item" v-model="selected" />
          </td>
        </tr>
      </tbody>
    </table>
  </div>


</body>

</html>

【讨论】:

以上是关于数组中对象的属性在所有元素都更改时是反应性的,但如果只有一些元素更改则不是的主要内容,如果未能解决你的问题,请参考以下文章

基于对象属性对数组元素的反应

VueJs 组件的 Prop 相关计算属性对对象数组 Prop 更改没有反应

如何根据反应中的状态属性对数组中的元素进行分组?

JavaScript 数组去重

javascript更改数组中的元素[重复]

如何在反应 js 代码中动态更改 css 选择器属性值?