表格(ant-design-vue)实现分页全选/分页多选功能

312 阅读3分钟

基础环境

  • vue: 2.6.10
  • antd: ^4.18.9
  • ant-design-vue: ^1.7.2

实现逻辑

通过isAll判断是否为全选所有,如果是的话配合excludeIds,否则配合includeIds的值完成

参考官方实现的自定义选项

1x.antdv.com/components/…

<template>
  <a-table :row-selection="rowSelection" :columns="columns" :data-source="data" />
</template>
<script>
const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
  },
  {
    title: 'Age',
    dataIndex: 'age',
  },
  {
    title: 'Address',
    dataIndex: 'address',
  },
];

const data = [];
for (let i = 0; i < 46; i++) {
  data.push({
    key: i,
    name: `Edward King ${i}`,
    age: 32,
    address: `London, Park Lane no. ${i}`,
  });
}

export default {
  data() {
    return {
      data,
      columns,
      selectedRowKeys: [], // Check here to configure the default column
    };
  },
  computed: {
    rowSelection() {
      const { selectedRowKeys } = this;
      return {
        selectedRowKeys,
        onChange: this.onSelectChange,
        hideDefaultSelections: true,
        selections: [
          {
            key: 'all-data',
            text: 'Select All Data',
            onSelect: () => {
              this.selectedRowKeys = [...Array(46).keys()]; // 0...45
            },
          },
          {
            key: 'odd',
            text: 'Select Odd Row',
            onSelect: changableRowKeys => {
              let newSelectedRowKeys = [];
              newSelectedRowKeys = changableRowKeys.filter((key, index) => {
                if (index % 2 !== 0) {
                  return false;
                }
                return true;
              });
              this.selectedRowKeys = newSelectedRowKeys;
            },
          },
          {
            key: 'even',
            text: 'Select Even Row',
            onSelect: changableRowKeys => {
              let newSelectedRowKeys = [];
              newSelectedRowKeys = changableRowKeys.filter((key, index) => {
                if (index % 2 !== 0) {
                  return true;
                }
                return false;
              });
              this.selectedRowKeys = newSelectedRowKeys;
            },
          },
        ],
        onSelection: this.onSelection,
      };
    },
  },
  methods: {
    onSelectChange(selectedRowKeys) {
      console.log('selectedRowKeys changed: ', selectedRowKeys);
      this.selectedRowKeys = selectedRowKeys;
    },
  },
};
</script>

通常我们实现的表格是分页的,后端每次只会返回当页的数据,所以上面的实现需要改造

  1. 我们自定义三个选项,分别是"选择所有"、“反选当页”和“清除所有”。
  2. 修改三个选项中的onSelect方法 (点击三个选项触发的回调函数)
  • 当点击“选择所有”,isAll=true,excludeIds=[],includeIds: []

  • 当选择“清除所有”,isAll=false,excludeIds=[],includeIds: []

  • 当选择“反选当页”

    a. 如果isAll=true,计算excludeIds

    • onSelect方法有一个参数changableRowKeys。

    • changableRowKeys是一个数组,值是当前页的所有行的key;

    • 遍历changableRowKeys,

    • 如果excludeIds中没有这一行的key,则添加;

    • 如果excludeIds中有这一行的key,则删除;

    b. 如果isAll=false,计算includeIds

    • 遍历changableRowKeys,
    • 如果includeIds中没有这一行的key,则添加;
    • 如果includeIds中有这一行的key,则删除;
  1. 修改onSelectChange方法(勾选每一行或当前页触发的回调函数)

    a. 如果isAll=true,计算excludeIdsexcludeIds取当前页没有勾选的

    • onSelectChange方法有一个参数selectedRowKeys。

    • changableRowKeys是一个数组,值是当前页的已勾选行的key;

    • 遍历data,

    • 如果selectedRowKeys中没有当前遍历项的key,且excludeIds中没有这一行的key,则添加;

    • 如果selectedRowKeys中有当前遍历项的key,且excludeIds中有这一行的key,则删除

    b. 如果isAll=false,计算includeIdsincludeIds取当前页勾选的

    • 遍历selectedRowKeys;
    • 如果includeIds中没有当前遍历项的key,则添加;
    • 如果includeIds中有当前遍历项的key,则删除;
export default {
  data() {
    return {
      data,
      columns,
      selectedRowKeys: [], // Check here to configure the default column
      isAll,
      excludeIds: [],
      includeIds: []
    };
  },
  computed: {
    rowSelection() {
      const { selectedRowKeys } = this;
      return {
        selectedRowKeys,
        onChange: this.onSelectChange,
        hideDefaultSelections: true,
        selections: [
          {
            key: 'all-data',
            text: '选择所有',
            onSelect: changableRowKeys => {
              this.isAll = true
              this.excludeIds = []
              this.includeIds = []
              this.selectedRowKeys = changableRowKeys
            },
          },
          {
            key: 'reverse-current-page',
            text: '反选当页',
            onSelect: changableRowKeys => {
              // 此时的changableRowKeys是当前页所有项
              let newSelectedRowKeys = []
              if (this.isAll) { // 全选时,计算excludeIds
                  changableRowKeys.forEach(key => {
                      let pos = this.excludeIds.indexOf(key)
                      if (pos >= 0) { // 反选,如果包含,则清除
                          this.excludeIds.splice(pos, 1)
                      } else { // 反选,如果不包含,则push
                          this.excludeIds.push(key)
                      }
                  })
                  
                  // 计算当前页勾选哪些项,此时勾选的项与excludeIds相反
                  newSelectedRowKeys = changableRowKeys.filter(key => {
                      return this.excludeIds.indexOf(key) === -1
                  })
              
              } else { // 非选择时,计算includeIds
                  changableRowKeys.forEach(key => {
                      let pos = this.excludeIds.indexOf(key)
                      if (pos >= 0) { // 反选,如果包含,则清除
                          this.excludeIds.splice(pos, 1)
                      } else { // 反选,如果不包含,则push
                          this.excludeIds.push(key)
                      }
                  })
                  // 计算当前页勾选哪些项,此时勾选的项与excludeIds相同
                  newSelectedRowKeys = this.excludeIds
              }
              
              this.selectedRowKeys = newSelectedRowKeys;
            },
          },
          {
            key: 'clear-all',
            text: '清除所有',
            onSelect: changableRowKeys => {
              this.isAll = false
              this.excludeIds = []
              this.includeIds = []
              this.selectedRowKeys = [];
            },
          },
        ],
        onSelection: this.onSelection,
      };
    },
  },
  methods: {
    onSelectChange(selectedRowKeys) {
      // 此时的selectedRowKeys是当前页勾选的项
      if (this.isAll) { //全选时,计算excludeIds
          this.data.forEach(item => {
              if (!this.selectedRowKeys.includes(item.key) && !this.excludeIds.includes(item.key)) {
                  this.excludeIds.push(item.key)
              }
          })
      } else { // 非全选时,计算includeIds
          this.selectedRowKeys.forEach(key => {
              if (!this.includeIds.includes(key)) this.includeIds.push(key)
          })
      }
      this.selectedRowKeys = selectedRowKeys;
    },
  },
};

111