【问题标题】:Standard "check-all" functionality in table表中的标准“检查所有”功能
【发布时间】:2021-08-30 21:12:33
【问题描述】:

这是我的网格 (CRUD) 组件的一部分:

<template>
  <table class="MyComponent table">
    <thead>
      <tr>
        <th width="30px">
          <b-form-checkbox v-model="allChecked" />
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(record, index) in records" :key="index">
        <td width="30px">
          <b-form-checkbox :value="record['id']" v-model="checkedRows" />
        </td>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  name: "MyComponent",
  components: {
  },
  props: ['config'],
  data() {
    return {
      records: [{
        id: 1
      }, {
        id: 2
      }, {
        id: 3
      }, {
        id: 4
      }, {
        id: 5
      }, {
        id: 6
      }],
      checkedRows: []
    }
  },
  computed: {
    allChecked: {
      get() {
        return this.records.length == this.checkedRows.length
      },
      set(v) {
        if(v) {
          this.checkedRows = [];
          for(var i in this.records) {
            this.checkedRows.push(this.records[i]['id'])
          }
        }
        else {
          this.checkedRows = [];
        }
      }
    }
  }
};
</script>

如您所见,我想实现一个标准的、广泛使用的功能:用户可以检查多行并对选定的行进行一些操作。问题在于表格顶部的“全选”复选框。当我检查所有时,然后我从下面的一个复选框中删除勾选,它取消选中页面上的所有复选框。

我理解它发生的原因:当我从下面的复选框中删除一个勾号时,“this.records.length == this.checkedRows.length”条件将不再为真,因此“allChecked”计算变量将设置为 false,因此顶部复选框将设置为未选中。问题是:当顶部的复选框被取消选中时,所有的复选框也将被取消选中,因为计算变量的“设置”部分。

Vue 中是否有干净的方法来解决这个问题?

【问题讨论】:

    标签: vue.js vuejs2


    【解决方案1】:

    我不确定你想对选中的行做什么,但也许这样会更好:

    <b-form-checkbox :value="record['id']" v-model="record.checked" />
    

    然后将records 中的对象添加到checked 属性中。

    records: [
        {
            id: 1,
            checked: false
        },
        ...
    ]
    

    如果你需要一个检查记录的列表,你可以做一个计算属性:

    computed: {
        checkedRecords() {
            return this.records.filter(record => record.checked);
        }
    }
    

    为了检查-取消检查所有你只需遍历所有记录:

    <b-form-checkbox @change="clickedAll" />
    
    methods: {
        clickedAll(value) {
            this.records = this.records.map(record => {
                  record.checked = value
                  return record
               }
        }
    }
    

    【讨论】:

    • 首先,感谢您的回答,但不幸的是它不起作用,它也失去了一个重要的功能。 v-model 将值保存到复选框中的数组中(请参阅vuejs.org/v2/guide/forms.html),因此 v-model 的“record.checked”不是一个好的解决方案。另一个问题如下:当用户手动检查下面的所有复选框时,我想选中“顶部”复选框(所以如果我有 10 行,并且我在行的开头选中了所有 10 个复选框, “顶部”复选框也应该被选中)。
    • 第二个问题可以轻松解决,但第一个问题我不明白为什么它不适合您的需求?是的,它确实将值保存到数组中,因此它可以绑定到复选框并具有反应性。这才是重点。你能解释一下为什么它不可接受吗?
    • 好的,我看到你找到了自己的解决方案。凉爽的。 :)
    【解决方案2】:

    好的,同时我解决了这个问题。这是我的解决方案。感谢@Eggon 的帮助,您提出了使用@change 方法的想法。

        <template>
          <table class="MyComponent table">
            <thead>
              <tr>
                <th width="30px">
                  <b-form-checkbox v-model="allChecked" @change="checkAll" />
                </th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(record, index) in records" :key="index">
                <td width="30px">
                  <b-form-checkbox :value="record['id']" v-model="checkedRows" />
                </td>
              </tr>
            </tbody>
          </table>
        </template>
        
        <script>
        export default {
          name: "MyComponent",
          components: {
          },
          props: ['config'],
          data() {
            return {
              records: [{
                id: 1
              }, {
                id: 2
              }, {
                id: 3
              }, {
                id: 4
              }, {
                id: 5
              }, {
                id: 6
              }],
              checkedRows: []
            }
          },
          methods: {
            checkAll(value) {
              if(!value) {
                this.checkedRows = [];
                return ;
              }
        
              var newCheckedRows = [];
              for(var i in this.records) {
                newCheckedRows.push(this.records[i].id)
              }
              this.checkedRows = newCheckedRows;
            }
          },
          computed: {
            allChecked: {
              get() {
                return this.records.length == this.checkedRows.length
              },
              set() {
                
              }
            }
          }
        };
        </script>
    

    【讨论】:

    • 我很好奇 - 它真的有效吗v-model="checkedRows"?我没想到会发生这种情况 - 您将一个被v-for 多次乘以的单个属性绑定到一个空数组。我不明白它们如何正确绑定。
    • @Eggon 当您使用具有相同 v-model 属性的多个复选框并且每个复选框具有不同的 :value 属性时,它会以这种方式工作。您可以在此处找到文档:vuejs.org/v2/guide/forms.html#Checkbox,在“多个复选框”部分下。我尝试了两种解决方案,你的和我的。您的解决方案不起作用,因为 record.checked 从复选框中获取 :value 属性(在您的情况下是一个 id),但您使用它就像一个布尔值。
    • 好的,我明白了,谢谢,我不知道复选框可以这样绑定。这很奇怪,因为在您链接的文档中有一个带有单个复选框的示例,它是按照我的方式完成的,但没有在那里定义值。也许这样会更好:b-form-checkbox v-model="record.checked"。但是,即使值是 ID,它也应该可以工作,因为 ID 是真的吗?但是没关系。 :) 祝你的项目好运!
    猜你喜欢
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-25
    相关资源
    最近更新 更多