element-ui的树形数据与懒加载这个似乎没办法级联选中,本来打算给rp一下的,但element的项目我实在是运行不起来,再者就算rp了,作者大概率也不会采纳。我就在业务模块中修改了一下.

级联勾选中,indeterminate(不确定状态)没有实现,也就是若所有的子节点被选中了,那么父节点会被勾选,若是有任意子节点未被选中,那么父节点不会被勾选,不会出现不确定状态

实现主要是通过el-table上面的两个事件selectselect-all来实现的,select-all是表格全选的事件,我发现全选的时候,除了一级的节点外,二三级节点都不会被选中,所以也实现了一下

我发现还有一种需求,是只要有任意一个子节点被选中,那么父节点就也被选中,所有的子节点都被取消选中,那么父节点也要取消选中,代码我也写到后面去了

这些操作完毕以后,要获取所有被选中的数据,这里数据可能需要被处理一下,因为对于每个选中数据,可能拥有children属性,而children属性下面的子数据可能并非是我们选中的数据,这些数据处理我也实现了,但上面两种情况的数据处理方式不太相同,若是真的有人需要的话可以跟我交流哈

示例地址 github



<template>
  <div id="app">
    <el-table
      ref="multipleTable"
      :data="tableData"
      style="width: 100%;margin-bottom: 20px;"
      row-key="id"
      border
      default-expand-all
      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
      @select="handleSelect"
      @select-all="handleSelectAll"
      @selection-change="debounceHandleSelectionChange"
    >
      <el-table-column
        type="selection"
        width="55"
      />
      <el-table-column
        prop="date"
        label="日期"
        sortable
        width="180"
      />
      <el-table-column
        prop="name"
        label="姓名"
        sortable
        width="180"
      />
      <el-table-column
        prop="address"
        label="地址"
      />
    </el-table>
  </div>
</template>

<script>
import { debounce } from 'lodash'
export default {
  data() {
    return {
      tableData: [{
        id: 1,
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      }, {
        id: 2,
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      }, {
        id: 3,
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 弄',
        children: [{
          id: 31,
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄',
          children: [{
            id: 311,
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            id: 312,
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            id: 313,
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }]
        }, {
          id: 32,
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄'
        }]
      }, {
        id: 4,
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 弄'
      }],
      multipleSelection: []
    }
  },
  created() {
    this.debounceHandleSelectionChange = debounce(this.handleSelectionChange)
  },
  methods: {
    handleSelectionChange(val) {
      console.log(val)
      this.multipleSelection = val
    },
    handleSelectAll() {
      const isAllSelected = this.$refs.multipleTable.store.states.isAllSelected
      var _handleSelectAll = (data) => {
        data.forEach(item => {
          this.$refs.multipleTable.toggleRowSelection(item, isAllSelected)
          _handleSelectAll(item.children || [])
        })
      }
      _handleSelectAll(this.tableData)
    },
    handleSelect(selection, current) {
      // 判断selection中是否存在current,若是存在那么就代表是被勾选上了,若是不存在代表是取消勾选了
      const isChecked = !!selection.find(item => item.id === current.id)
      // 如果当前项被取消勾选
      if (!isChecked) {
        // 那么其所有的祖先也应该被取消勾选
        this.uncheckedParents(selection, current)
        // 那么其所有的后代也应该被取消勾选
        this.toggleCheckedChildrens(selection, current, false)
      } else { // 如果当前项被勾选
        // 那么若同一组的元素都被勾选了,那么父元素将也被勾选,依次往上类推
        this.checkedParents(selection)
        // 那么其所有的后代都要被勾选
        this.toggleCheckedChildrens(selection, current, true)
      }
    },
    toggleCheckedChildrens(selection, item, isChecked) {
      var _toggleCheckedChildrens = (data) => {
        data.find(element => {
          this.$refs.multipleTable.toggleRowSelection(element, isChecked)
          if (isChecked && !selection.find(item => item.id === element.id)) {
            selection.push(element)
          } else if (!isChecked && selection.find(item => item.id === element.id)) {
            for (let i = selection.length - 1; i >= 0; i--) {
              if (selection[i].id === element.id) {
                selection.splice(i, 1)
                break
              }
            }
          }
          _toggleCheckedChildrens(element.children || [])
        })
      }
      _toggleCheckedChildrens(item.children || [])
    },
    checkedParents(selection) {
      var _checkedParents = (element) => {
        const children = element.children
        if (children && children.length) {
          const allChildrenChecked = children.every(child => {
            return _checkedParents(child)
          })
          if (allChildrenChecked) {
            this.$refs.multipleTable.toggleRowSelection(element, true)
            if (!selection.find(item => item.id === element.id)) {
              selection.push(element)
            }
          }
        }
        return selection.find(item => item.id === element.id)
      }
      this.tableData.forEach(element => {
        _checkedParents(element)
      })
    },
    uncheckedParents(selection, item) {
      var _uncheckedParents = (data) => {
        return data.find(element => {
          if (element.id === item.id) {
            return true
          } else if (_uncheckedParents(element.children || [])) {
            this.$refs.multipleTable.toggleRowSelection(element, false)
            for (let i = selection.length - 1; i >= 0; i--) {
              if (selection[i].id === element.id) {
                selection.splice(i, 1)
                break
              }
            }
            return true
          } else {
            return false
          }
        })
      }
      _uncheckedParents(this.tableData)
    }
  }
}
</script>



只要有任意一个子节点被选中,那么父节点就也被选中的代码示例



<template>
  <div id="app">
    <el-table
      ref="multipleTable"
      :data="tableData"
      style="width: 100%;margin-bottom: 20px;"
      row-key="id"
      border
      default-expand-all
      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
      @select="handleSelect"
      @select-all="handleSelectAll"
      @selection-change="debounceHandleSelectionChange"
    >
      <el-table-column
        type="selection"
        width="55"
      />
      <el-table-column
        prop="date"
        label="日期"
        sortable
        width="180"
      />
      <el-table-column
        prop="name"
        label="姓名"
        sortable
        width="180"
      />
      <el-table-column
        prop="address"
        label="地址"
      />
    </el-table>
  </div>
</template>

<script>
import { debounce } from 'lodash'
export default {
  data() {
    return {
      tableData: [{
        id: 1,
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      }, {
        id: 2,
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      }, {
        id: 3,
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 弄',
        children: [{
          id: 31,
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄',
          children: [{
            id: 311,
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            id: 312,
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            id: 313,
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }]
        }, {
          id: 32,
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄'
        }]
      }, {
        id: 4,
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 弄'
      }],
      multipleSelection: []
    }
  },
  created() {
    this.debounceHandleSelectionChange = debounce(this.handleSelectionChange)
  },
  methods: {
    handleSelectionChange(val) {
      console.log(val)
      this.multipleSelection = val
    },
    handleSelectAll(selection) {
      const isAllSelected = this.$refs.multipleTable.store.states.isAllSelected
      var _handleSelectAll = (data) => {
        data.forEach(item => {
          this.$refs.multipleTable.toggleRowSelection(item, isAllSelected)
          _handleSelectAll(item.children || [])
        })
      }
      _handleSelectAll(this.tableData)
    },
    handleSelect(selection, current) {
      // 判断selection中是否存在current,若是存在那么就代表是被勾选上了,若是不存在代表是取消勾选了
      const isChecked = !!selection.find(item => item.id === current.id)
      // 如果当前项被取消勾选
      if (!isChecked) {
        // 那么其所有的后代也应该被取消勾选
        this.toggleCheckedChildrens(selection, current, false)
        // 那么若是所有的兄弟都被取消勾选的话,其祖先也应该被取消勾选
        this.uncheckedParents(selection, current)
      } else { // 如果当前项被勾选
        // 那么若同一组的元素都被勾选了,那么父元素将也被勾选,依次往上类推
        this.checkedParents(selection)
        // 那么其所有的后代都要被勾选
        this.toggleCheckedChildrens(selection, current, true)
      }
    },
    toggleCheckedChildrens(selection, item, isChecked) {
      var _toggleCheckedChildrens = (data) => {
        data.find(element => {
          this.$refs.multipleTable.toggleRowSelection(element, isChecked)
          if (isChecked && !selection.find(item => item.id === element.id)) {
            selection.push(element)
          } else if (!isChecked && selection.find(item => item.id === element.id)) {
            for (let i = selection.length - 1; i >= 0; i--) {
              if (selection[i].id === element.id) {
                selection.splice(i, 1)
                break
              }
            }
          }
          _toggleCheckedChildrens(element.children || [])
        })
      }
      _toggleCheckedChildrens(item.children || [])
    },
    checkedParents(selection) {
      var _checkedParents = (element) => {
        const children = element.children
        if (children && children.length) {
          const anyChildrenChecked = children.some(child => {
            return _checkedParents(child)
          })
          if (anyChildrenChecked) {
            this.$refs.multipleTable.toggleRowSelection(element, true)
            if (!selection.find(item => item.id === element.id)) {
              selection.push(element)
            }
          }
        }
        return selection.find(item => item.id === element.id)
      }
      this.tableData.forEach(element => {
        _checkedParents(element)
      })
    },
    uncheckedParents(selection, item) {
      var _uncheckedParents = (element) => {
        const children = element.children
        if (children && children.length) {
          const allChildrenUnChecked = children.every(child => {
            return _uncheckedParents(child)
          })
          if (allChildrenUnChecked) {
            this.$refs.multipleTable.toggleRowSelection(element, false)
            for (let i = selection.length - 1; i >= 0; i--) {
              if (selection[i].id === element.id) {
                selection.splice(i, 1)
                break
              }
            }
            return true
          } else {
            return false
          }
        }
        return selection.every(item => item.id !== element.id)
      }
      this.tableData.forEach(element => {
        _uncheckedParents(element)
      })
    }
  }
}
</script>