el-table的树形结构结合多选框使用,实现单选父子联动,全选,反选功能

Element UI组件的树形结构结合多选框使用,目前是没有的,现在遇到了个需求,需要点击全选按钮,选中全部;点击父节点需选中其所有子节点,点击子节点需反选其父节点。

对上述需求,我封装了一个较为完整的组件来实现:

效果:

el-table的树形结构结合多选框使用,实现单选父子联动,全选,反选功能_第1张图片

实现思路

1.表格增加一列选择项,并使用el-checkbox来勾选,自定义标题(也添上复选框,用来做全选,取消全选功能)

2.需要后端配合返回每列数据含有每列数据的勾选状态的字段,如有需要禁用(那也得返回禁用状态的字段),可配置selectionConfig来自定义勾选状态和禁用状态的字段名

3.实现全选功能:声明一个全选状态的字段,然后遍历table数据,并将每条数据赋值选状态字段的值,如有子节点,递归遍历其子节点并赋值

4.单选其中一列数据:设置其子节点的状态,寻找其父节点,如有父节点,则遍历其父节点所有的子节点,判断是否都为选中状态。接着递归往上遍历其父节点。最后遍历到顶级节点,没有父节点,判断顶级节点是否都为选中,是则将全选状态的字段设为true

 全选功能部分代码

// 全选
setCheckAll() {
  this.tableData.forEach(item => {
    if (!item[this.selectionConfig.disabled]) {
      item[this.selectionConfig.checked] = this.selectAll
    }
    this.setChildren(item, this.selectAll)
  })
}

// 设置子节点
setChildren(row, checked) {
  if (row[this.treeProps.children]) {
    row[this.treeProps.children].forEach(item => {
      if (!item[this.selectionConfig.disabled]) {
        item[this.selectionConfig.checked] = checked
      }
      if (row[this.treeProps.children]) {
        this.setChildren(item, checked)
      }
    })
  }
},

单选功能部分代码

// 单选
setCheck(row) {
  // 设置该单元格所有子节点状态
  this.setChildren(row, row[this.selectionConfig.checked])
  let result = this.setParentCheck(row)
  // 遍历到顶级,顶级无父节点,判断顶级节点是否都为选中
  if (!result) {
    let isAll = this.tableData.every(item => {
      return item[this.selectionConfig.checked]
    })
    this.selectAll = isAll
  }
},
// 设置父节点
setParentCheck(row) {
  // 寻找该行数据的父节点
  let parent = null
  for (let i = 0; i < this.tableData.length; i++) {
    parent = this.findItem(this.tableData[i], row.parentId)
    if (parent != null) {
      break
    }
  }
  // 遍历该行的父节点下,所有的子节点
  if (parent != null) {
    if (parent[this.treeProps.children]) {
      // 子节点是否全都选中,如果是则则勾选该节点
      let isAll = parent[this.treeProps.children].every(item => {
        return item[this.selectionConfig.checked]
      })
      parent[this.selectionConfig.checked] = isAll
      // 递归查找该行父级的父级节点
      this.setParentCheck(parent, parent[this.selectionConfig.checked])
    }
  } else { // 遍历到顶级,停止
    return null
  }
},
// 查递归找该行的父节点
findItem(row, id) {
  if (row.id == id) {
    return row
  }
  if (row[this.treeProps.children]) {
    let parent = null
    for (let i = 0; i < row[this.treeProps.children].length; i++) {
      parent = this.findItem(row[this.treeProps.children][i], id)
      if (parent) {
        break
      }
    }
    return parent
  } else {
    return null
  }
}

完整代码:





你可能感兴趣的:(组件封装,前端)