插件窝 干货文章 Element UI el-tree组件自定义复选框:如何实现第一个复选框的反选及父子节点联动?

Element UI el-tree组件自定义复选框:如何实现第一个复选框的反选及父子节点联动?

复选框 节点 tree data 587    来源:    2025-03-26

Element UI el-tree 自定义复选框实现方案

要实现 Element UI 中 el-tree 组件的自定义复选框功能,包括第一个复选框的反选及父子节点联动,可以采用以下解决方案:

方案一:使用 render-content 自定义渲染

<template>
  <el-tree
    :data="data"
    show-checkbox
    node-key="id"
    :default-expanded-keys="[2, 3]"
    :default-checked-keys="[5]"
    :render-content="renderContent"
    @check="handleCheck"
  ></el-tree>
</template>

<script>
export default {
  data() {
    return {
      data: [{
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: '二级 1-1',
          children: [{
            id: 9,
            label: '三级 1-1-1'
          }, {
            id: 10,
            label: '三级 1-1-2'
          }]
        }]
      }]
    }
  },
  methods: {
    renderContent(h, { node, data, store }) {
      return h('span', {
        class: 'custom-tree-node'
      }, [
        // 第一个复选框
        h('el-checkbox', {
          style: { 'margin-right': '8px' },
          on: {
            change: (checked) => this.handleFirstCheckbox(checked, node)
          }
        }),
        h('span', node.label)
      ]);
    },
    handleFirstCheckbox(checked, node) {
      // 反选逻辑
      const tree = this.$refs.tree;
      if (checked) {
        tree.setChecked(node, false);
      } else {
        tree.setChecked(node, true);
      }
    },
    handleCheck(currentNode, checkedNodes) {
      // 父子节点联动逻辑
      const tree = this.$refs.tree;
      const childNodes = currentNode.childNodes;

      if (childNodes && childNodes.length > 0) {
        childNodes.forEach(child => {
          tree.setChecked(child, currentNode.checked);
        });
      }
    }
  }
}
</script>

方案二:使用 check-strictly 和自定义事件处理

<template>
  <el-tree
    ref="tree"
    :data="data"
    show-checkbox
    node-key="id"
    :check-strictly="true"
    @check-change="handleCheckChange"
  ></el-tree>
</template>

<script>
export default {
  data() {
    return {
      data: [/* 同上 */]
    }
  },
  methods: {
    handleCheckChange(data, checked, indeterminate) {
      // 反选第一个复选框
      if (data.id === 1) {
        this.$nextTick(() => {
          this.$refs.tree.setChecked(data.id, !checked);
        });
      }

      // 父子节点联动
      if (checked && data.children) {
        data.children.forEach(child => {
          this.$refs.tree.setChecked(child.id, true);
        });
      }
    }
  }
}
</script>

关键点说明

  1. 反选实现

    • 通过监听复选框的 change 事件,在回调中手动调用 setChecked 方法设置相反的状态
    • 或者使用 check-change 事件,在回调中通过 $nextTick 延迟设置相反状态
  2. 父子节点联动

    • 当父节点被选中时,遍历其子节点并设置为相同状态
    • 可以使用 setChecked 方法批量设置子节点状态
  3. 注意事项

    • 使用 check-strictly 可以解除 Element UI 默认的父子关联
    • 自定义渲染时要注意样式的一致性
    • 大数据量时考虑性能优化

扩展功能

如果需要实现更复杂的逻辑,如: - 子节点全选时自动选中父节点 - 部分选中时的半选状态 - 异步加载时的联动处理

可以在 handleCheckChange 方法中添加相应逻辑,或使用 getHalfCheckedNodes 方法获取半选节点状态。

希望以上方案能解决您的问题!