1. Demand background

The user needs to display some default checked data (output data) and unoperable data (gray data) during table initialization: Disable =true), when the check is complete, the current check result will be saved as the output data of the next table (this application will be encountered in the scenario combined with popover). Therefore, this article adds two new arrays on the logic above:

  • 1. The array redisplayData is displayed
  • 2. Set the grey array setDisableData

2. Mind mapping

3. Relevant codes

3.1 Encapsulated table component code

// STable.vue
<template>
  <div class="s-table">
    <el-table
      ref="innerTable"
      class="table"
      style="width: 100%"
      :row-key="getRowKeys"
      :data="tableData"
      :total="total"
      v-bind="$attrs"
      @select="select"
      @select-all="selectAll"
      v-on="$listeners"
    >
      <el-table-column
        v-if="selectable"
        type="selection"
        width="80"
        :reserve-selection="true"
        :selectable="selectableHandler"
      ></el-table-column>
      <el-table-column
        v-for="(item) in columns"
        :key="item.prop"
        :prop="item.prop"
        :label="item.label"
        :sortable="item.sortable"
        :width="parseInt(item.width)"
      >
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  name: 'STable',
  props: {

    // 默认列
    columns: {
      type: Array,
      default: () => []
    },
    tableData: {
      type: Array,
      default: () => []
    },
    // 是否可选
    selectable: {
      type: Boolean,
      default: false
    },
    // 是否跨页全选
    isSelectedAll: {
      type: Boolean,
      default: false
    },
    // table表格的总数据条数
    total: {
      type: Number,
      default: 0
    },
    // 回显数据
    redisplayData: {
      type: Array,
      default: () => []
    },
    // 置灰数据
    setDisableData: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      uncheckedArr: [],
      ifRedisplay: false,
      redisplayArr: [], // 克隆接收到的redisplayData的值
      disabledCheckedArr: [], // 被勾选的置灰数据
      disabledUnCheckedArr: [] // 未被勾选的置灰数据(不可勾选)
    }
  },
  watch: {
    // 分页全选-监听数据变化
    tableData: {
      handler (value) {
        this.isSelectedAll && this.chooseAllPages(this.isSelectedAll)
        !this.isSelectedAll && this.checkedSelected()
        this.ifRedisplay && this.redisplayHandler()
        this.$nextTick(() => {
          if (this.uncheckedArr.length === 0 && this.$refs.innerTable.selection.length === this.total - this.disabledUnCheckedArr.length) {
            this.$emit('update:isSelectedAll', true)
          }
        })
      },
      deep: true
    }
  },
  mounted() {
    if (document) {
      document.addEventListener('click', this.hideSettings)
    }
    this.redisplayData.length > 0 ? this.ifRedisplay = true : this.ifRedisplay = false
    this.redisplayArr = JSON.parse(JSON.stringify(this.redisplayData))
    this.ifRedisplay && this.redisplayHandler()
    this.setDisableData.length > 0 && this.disabledArrHandler()
  },
  methods: {
    getRowKeys(row) {
      return row.id
    },
    // 全选所有页面
    chooseAllPages(val) {
      if (val) {
        // 全选
        this.$nextTick(() => {
          let choosedArr = []
          this.tableData.map(row => {
            if (this.setDisableData.map(v => v.id).indexOf(row.id) < 0) {
              choosedArr.push(row)
            }
          })
          choosedArr.forEach(row => {
            this.$refs.innerTable.toggleRowSelection(row, true)
          })
        })
      } else {
        // 取消全选
        this.uncheckedArr = []
        this.redisplayArr = []
        this.$nextTick(() => {
          this.$refs.innerTable.clearSelection()
          this.$nextTick(() => {
            this.tableData.forEach(row => {
              if (this.disabledCheckedArr.map(v => v.id).indexOf(row.id) >= 0) {
                this.$refs.innerTable.toggleRowSelection(row, true)
              }
            })
          })
        })
      }
    },
    // 切换分页时选择之前选中
    checkedSelected() {
      if (this.isSelectedAll) {
        // 全选状态
        this.$nextTick(() => {
          this.tableData.forEach(row => {
            this.$refs.innerTable.toggleRowSelection(row, true)
          })
        })
      } else {
        // 非全选状态下
        if (this.uncheckedArr.length > 0) {
          this.$nextTick(() => {
            this.tableData.forEach(row => {
              if ((this.uncheckedArr.map(v => v.id).indexOf(row.id) < 0) && (this.disabledUnCheckedArr.map(v => v.id).indexOf(row.id) < 0)) {
                this.$refs.innerTable.toggleRowSelection(row, true)
              }
              if (this.disabledCheckedArr.map(v => v.id).indexOf(row.id) >= 0) {
                this.$refs.innerTable.toggleRowSelection(row, true)
              }
            })
          })
        }
        this.$nextTick(() => {
          this.tableData.forEach(row => {
            if (this.disabledCheckedArr.map(v => v.id).indexOf(row.id) >= 0) {
              this.$refs.innerTable.toggleRowSelection(row, true)
            }
          })
        })
      }
    },
    // 全选后取消单个选择事件,当用户手动勾选数据行的 Checkbox 时触发的事件
    select(selection, row) {
      this.selectExceptCardIds(selection, row)
      this.$emit('select', [selection, row])
    },
    // 单个选择事件
    selectExceptCardIds(selection, row) {
      if (this.isSelectedAll) {
        // 全选状态下,列表行数据都处于被选中状态,手动勾选只能触发取消选中
        this.uncheckedArr.push(row)
        if (this.ifRedisplay) {
          this.redisplayArr.map((v, index) => {
            if (row.id === v.id) {
              this.redisplayArr.splice(index, 1)
            }
          })
        }
        this.$emit('update:isSelectedAll', false)
      } else {
        // false, 非全选状态下,列表行数据可能被 取消选中 或者 重新勾选
        if (selection.indexOf(row) >= 0) {
          // 勾选
          selection.map(el => {
            this.uncheckedArr.map((v, index) => {
              if (el.id === v.id) {
                this.uncheckedArr.splice(index, 1)
                if (this.uncheckedArr.length === 0) {
                  this.$emit('update:isSelectedAll', true)
                }
              }
            })
          })
        } else {
          // 取消勾选
          // 1、若是uncheckedArr.length > 0,取消勾选的数组加入uncheckedArr
          if (this.uncheckedArr.length > 0) {
            this.uncheckedArr.push(row)
          }
          // 有回显数的取消勾选
          if (this.ifRedisplay) {
            this.redisplayArr.map((v, index) => {
              if (row.id === v.id) {
                this.redisplayArr.splice(index, 1)
              }
            })
          }
        }
        if (selection.length === this.total - this.disabledUnCheckedArr.length) {
          this.$emit('update:isSelectedAll', true)
        }
      }
    },
    // 全选后取消单页选择事件,当用户手动勾选数据行的 Checkbox 时触发的事件
    selectAll(selection) {
      this.selectAllRows(selection)
      this.$emit('selectAll', selection)
    },
    // 单页选择事件
    selectAllRows(selection) {
      if (this.isSelectedAll) {
        // 全选状态下,列表行数据都处于被选中状态,手动勾选只能触发取消选中
        this.tableData.map(row => {
          this.uncheckedArr.push(row)
          if (this.ifRedisplay) {
            this.redisplayArr.map((v, index) => {
              if (row.id === v.id) {
                this.redisplayArr.splice(index, 1)
              }
            })
          }
        })
        this.$emit('update:isSelectedAll', false)
      } else {
        // false,部分选中状态下
        selection.map(row => {
          // 勾选
          this.uncheckedArr.map((v, index) => {
            if (row.id === v.id) {
              this.uncheckedArr.splice(index, 1)
            }
            if (this.uncheckedArr.length === 0) {
              this.$emit('update:isSelectedAll', true)
            }
          })
          // 取消勾选
          if (this.uncheckedArr.length > 0 && this.tableData.map(v => v.id).indexOf(row.id) === -1) {
            this.uncheckedArr.push(row)
          }
          // 有回显数据
          if (this.ifRedisplay) {
            this.redisplayArr.map((v, index) => {
              if (row.id === v.id) {
                this.redisplayArr.splice(index, 1)
              }
            })
          }
        })
        if (selection.length === this.total - this.disabledUnCheckedArr.length) {
          this.$emit('update:isSelectedAll', true)
        }
      }
    },
    // 回显数据
    redisplayHandler() {
      if (this.redisplayArr.length > 0) {
        this.$nextTick(() => {
          this.tableData.forEach(row => {
            if (this.redisplayArr.map(v => v.id).indexOf(row.id) >= 0) {
              this.$refs.innerTable.toggleRowSelection(row, true)
            }
          })
        })
      }
    },
    // 置灰数组处理
    disabledArrHandler() {
      if (this.redisplayData.length > 0) {
        this.setDisableData.map(row => {
          if (this.redisplayData.map(v => v.id).indexOf(row.id) > 0) {
            this.disabledCheckedArr.push(row)
          } else {
            this.disabledUnCheckedArr.push(row)
          }
        })
      }
    },
    // 置灰操作
    selectableHandler(row, index) {
      let flag = true
      for (let i = 0; i < this.setDisableData.length; i++) {
        if (row.id === this.setDisableData[i].id) {
          flag = false
        }
      }
      return flag
    }
  }
}
</script>
<style lang="scss">
</style>

Copy the code

3.2 Sample Code

// example. Vue <template> <el-card> <el-checkbox v-model="isSelectedAll" @change="checkboxChange" > </el-checkbox> <s-table ref="accessControlTable" :table-data="tableData.slice((currentPage - 1) * pageSize, currentPage * pageSize)" :redisplay-data="redisplayData" :set-disable-data="setDisableData" :columns="columns" :selectable="true" :total="tableData.length" :is-selected-all.sync="isSelectedAll" > </s-table> <el-pagination Class = "s - pagination" : the currrent - page = "currentPage" : page - size = "pageSize:" page - sizes = ",10,20,30 [5]" :total="tableData.length" layout="total, prev, pager, next, sizes, jumper" @current-change="handleCurrentChange" @size-change="handleSizeChange" > </el-pagination> </el-card> </template> <script> import STable from '.. /components/STable.vue' export default { name: 'selectedAll', components: { STable }, data() { return { tableData: [{id: 1, date: '2016-05-02', name: 'Wang Xiaohu ', address:' 1518 Lane, Jinshajiang Road, Putao District, Shanghai '}, {id: 2, date: '2016-05-03', name: Date: '2016-05-04', date: '2016-05-04', name: '2016-05-04', address: '2016-05-04', {id: 4, Date: '2016-05-05', name: 'wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 5, date: '2016-05-06', name: 'Wang Xiaohu ', address: Date: '2016-05-07', name: 'Wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 7, Date: '2016-05-08', name: 'Wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 8, Date: '2016-05-09', name: 'Wang Xiaohu ', address: '1518 Jinshajiang Road, Putuo District, Shanghai'}, {id: 9, date: '2016-05-10', name: 'Wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 10, Date: '2016-05-11', name: 'Wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 11, Date: '2016-05-12', name: 'Wang Xiaohu ', address: }, redisplayData: [{id: 1, date: '2016-05-02', name: 'wang Xiaohu ', address: '1518 Jinshajiang Road, Putuo District, Shanghai'}, {id: 3, date: '2016-05-04', address: '1518 Jinshajiang Road, Putuo District, Shanghai'}, {id: 5, Date: '2016-05-06', name: 'Wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 8, Date: '2016-05-09', name: 'Wang Xiaohu ', address: '1518 Jinshajiang Road, Putuo District, Shanghai'}, {id: 10, date: '2016-05-09', name: 'Wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 11, Date: '2016-05-12', date: '2016-05-03', date: '2016-05-03', date: '2016-05-03', date: '2016-05-03', date: '2016-05-03', date: '2016-05-03' Date: '2016-05-04', date: '2016-05-04', name: '2016-05-04', address: '2016-05-04', {id: 4, Date: '2016-05-05', name: 'wang Xiaohu ', address:' 1518 Jinshajiang Road, Putuo District, Shanghai '}, {id: 7, date: '2016-05-08', name: 'Wang Xiaohu ', address: '1518 Jinshajiang Road, Putuo District, Shanghai'}, {id: 10, Date: '2016-05-11', name: address: '1518 Jinshajiang Road, Putuo District, Shanghai'}], columns: [{label: 'Date ', prop: 'date', width: 180}, {label: 'name', prop: 'name', width: 180}, {label:' address ', prop: 'date', width: 180}, {label: 'address ', prop: 'address'}], currentPage: 1, pageSize: 5, total: 0, isSelectedAll: false}}, methods: { handleSizeChange(val) { this.currentPage = 1 this.pageSize = val }, handleCurrentChange(val) { this.currentPage = val }, / / manually click change selection/not all state trigger event checkboxChange (val) {this. $refs. AccessControlTable. ChooseAllPages (val)}}} < / script > < style scoped> .s-pagination { text-align: right; margin-top: 10px; } </style>Copy the code

4. Related attributes and methods

Property or method name instructions type An optional value The default value
columns The default column Array []
tableData Tabular data Array []
selectable Whether or not an optional Boolean true/false false
isSelectedAll Whether to select all across the page Boolean true/false false
total The total number of entries in table data Number 0
redisplayData The echo data Array []
setDisableData Buy grey data Array []
chooseAllPages Select all pages Function

Note: isSelectedAll indicates whether all the table data is selected. Users can set the initial state by passing it in. If it is set to true, all the initial default Settings are selected. ChooseAllPages user manually changes isSelectedAll value, need to call trigger chooseAllPages event; Note: To implement cross-page selection, the tableData passed in must contain the ID attribute;