el-table多级复选框全选与反选

问题描述

使用el-table结合tree结构和CheckBox实现二级复选框的全选与反选。

页面结构

<el-table
  :data="dataList"
  highlight-current-row
  row-key="auditTypeId"
  :expand-row-keys="expandKeys"
  :tree-props="{ children: 'children', hasChildren: '!children.length' }"
>
  <el-table-column width="50" type="index">
    <template slot="header">
      <el-checkbox v-model="allCheck" :indeterminate="indeterminate" @change="allCheckChange"></el-checkbox>
    </template>
    <template slot-scope="{ row }">
      <el-checkbox
        v-model="row.checked"
        :indeterminate="row.indeterminate"
        @change="changeItem($event, row)"
      ></el-checkbox>
    </template>
  </el-table-column>
  <el-table-column prop="name" label="名称"></el-table-column>
</el-table>

选择逻辑

/**
 * @Description: 全选反选
 */
allCheckChange(val) {
  this.allCheck = val
  this.indeterminate = false

  const list = cloneDeep(this.dataList)
  list.forEach(itemA => {
    itemA.checked = val
    itemA.indeterminate = false

    itemA.children.forEach(itemB => {
      itemB.checked = val
    })
  })
  this.dataList = list
},

/**
 * @Description: 单选一行
 */
changeItem(val, row) {
  if (row.children) {
    row.children.forEach(item => {
      item.checked = val
    })
  } else {
    const fItem = findItemByProp(this.dataList, 'auditTypeId', row.parentGuid)
    const isChildAllCheck = fItem.children.every(item => {
      return item.checked
    })
    const isOneCheck = fItem.children.some(item => {
      return item.checked
    })
    const list = cloneDeep(this.dataList)
    for (let i = 0; i < list.length; i++) {
      const item = list[i]
      if (item.auditTypeId === row.parentGuid) {
        item.checked = isChildAllCheck
        item.indeterminate = !isChildAllCheck
        if (!val && !isOneCheck) {
          item.indeterminate = false
        }
        break
      }
    }
    this.dataList = list
  }

  this.allCheck = this.dataList.every(item => {
    return item.checked
  })
  if (this.allCheck) {
    this.indeterminate = false
  } else {
    this.indeterminate = this.getCheckedData().length > 0
  }
},

/**
 * @Description: 获取选择的数据
 * @param {*}
 * @return {*}
 */
getCheckedData() {
  const arr = []
  this.dataList.forEach(itemA => {
    itemA.children.forEach(itemB => {
      if (itemB.checked) {
        arr.push(itemB)
      }
    })
  })
  return arr
},

/**
 * @Description: 递归遍历树初始化数据(返显数据)
 * @param {*} data
 * @return {*}
 */
recursiveProcess(data) {
  const vm = this
  vm.selMap.clear()
  this.expandKeys = []
  let ids = []
  if (this.curOptions.select.length) {
    const ops = this.curOptions.options
    ids = getPropFromArr(ops, 'val')
  }
  const set = new Set()

  const initData = list => {
    list.forEach(item => {
      item.checked = false
      item.indeterminate = false
      if (ids.includes(item.auditTypeId)) {
        item.checked = true

        // 只保留子级选择的数据
        const fItem = findItemByProp(data, 'auditTypeId', item.parentGuid)
        set.add(fItem.auditTypeId)
        vm.selMap.set(fItem.auditTypeId, item)
      }
      if (item.children) {
        initData(item.children)
      }
    })

    this.expandKeys = [...set]
  }
  initData(data)
},

上一篇:javascript


下一篇:Vue 事件结合双向数据绑定实现todolist 待办事项 已经完成 和进行中<优化>