el-table 树形结构 多选 父子级联动 全选 半选状态

该代码示例展示了如何在ElementUI的Table组件中处理树形结构数据的多选框,包括初始化数据、复选框点击事件、全选事件以及行和头的样式处理,确保在选中父级时能正确影响子级的选中状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<template>
  <el-table :data="renderDynamic" ref="product" border row-key="id" :row-class-name="rowClassNameFun"
            :header-row-class-name="headerRowClassName" size="mini" max-height="500px" style="width: 100%"
            @select="selectFun" @select-all="selectAllFun" :header-cell-style="{ background: '#fafafa' }">
    <el-table-column type="selection" width="55"> </el-table-column>
    <el-table-column prop="date" label="日期" sortable width="180">
    </el-table-column>
    <el-table-column prop="name" label="姓名" sortable width="180">
    </el-table-column>
    <el-table-column prop="address" label="地址"> </el-table-column>
  </el-table>
</template>
<script>
export default {
  name: "TaskManage",
  data() {
    return {

      renderDynamic: [{
        id: 1,
        parentId: 0,
        date: "2016-05-02",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄",
      }, {
        id: 2,
        parentId: 0,
        date: "2016-05-01",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1519 弄",
        children: [{
          id: 3,
          parentId: 2,
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1519 弄",
          children: [{
            id: 4,
            parentId: 3,
            date: "2016-05-01",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1519 弄",
          }, {
            id: 5,
            parentId: 3,
            date: "2016-05-01",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1519 弄",
          }, ],
        }, {
          id: 6,
          parentId: 2,
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1519 弄",
        }, ],
      }, ],

    };

  },
  // isSelect状态:true为选中状态,false为未选中状态 ,空字符串为未知状态
  mounted() {
    this.initData(this.renderDynamic);
  },
  methods: {
    //初始化数据
    initData(data) {

      data.forEach((item) => {

        item.isSelect = false; //默认为不选中

        if (item.children && item.children.length) {

          this.initData(item.children);
        }
      });
    },
    // 复选框点击事件
    selectFun(selection, row) {
      this.setRowIsSelect(row);

    },
    // 复选框点击事件
    setRowIsSelect(row) {
      //当点击父级点复选框时,当前的状态可能为未知状态,所以当前行状态设为false并选中,即可实现子级点全选效果

      if (row.isSelect === "") {

        row.isSelect = false;

        this.$refs.product.toggleRowSelection(row, true);

      }
      row.isSelect = !row.isSelect;

      let that = this;

      function selectAllChildrens(data) {

        data.forEach((item) => {

          item.isSelect = row.isSelect;

          that.$refs.product.toggleRowSelection(item, row.isSelect);

          if (item.children && item.children.length) {

            selectAllChildrens(item.children);

          }

        });

      }
      function getSelectStatus(selectStatuaArr, data) {

        data.forEach((childrenItem) => {

          selectStatuaArr.push(childrenItem.isSelect);

          if (childrenItem.children && childrenItem.children.length) {

            getSelectStatus(selectStatuaArr, childrenItem.children);

          }

        });

        return selectStatuaArr;

      }

      function getLevelStatus(row) {

        //如果当前节点的parantId =0 并且有子节点,则为1

        //如果当前节点的parantId !=0 并且子节点没有子节点 则为3

        if (row.parentId == 0) {

          if (row.children && row.children.length) {

            return 1;

          } else {

            return 4;

          }

        } else {

          if (!row.children || !row.children.length) {

            return 3;

          } else {

            return 2;

          }

        }

      }

      let result = {};

      //获取明确的节点

      function getExplicitNode(data, parentId) {

        data.forEach((item) => {

          if (item.id == parentId) {

            result = item;

          }

          if (item.children && item.children.length) {

            getExplicitNode(item.children, parentId);

          }

        })

        return result;

      }

      function operateLastLeve(row) {

        //操作的是子节点  1、获取父节点  2、判断子节点选中个数,如果全部选中则父节点设为选中状态,如果都不选中,则为不选中状态,如果部分选择,则设为不明确状态

        let selectStatuaArr = [];

        let item = getExplicitNode(that.renderDynamic, row.parentId);

        selectStatuaArr = getSelectStatus(selectStatuaArr, item.children);

        if (

          selectStatuaArr.every((selectItem) => {

            return true == selectItem;

          })

        ) {

          item.isSelect = true;

          that.$refs.product.toggleRowSelection(item, true);

        } else if (

          selectStatuaArr.every((selectItem) => {

            return false == selectItem;

          })

        ) {

          item.isSelect = false;

          that.$refs.product.toggleRowSelection(item, false);

        } else {

          item.isSelect = "";

        }

        //则还有父级

        if (item.parentId != 0) {

          operateLastLeve(item)

        }

      }

      //判断操作的是子级点复选框还是父级点复选框,如果是父级点,则控制子级点的全选和不全选

      //1、只是父级 2、既是子集,又是父级 3、只是子级

      let levelSataus = getLevelStatus(row);

      if (levelSataus == 1) {

        selectAllChildrens(row.children);

      } else if (levelSataus == 2) {

        selectAllChildrens(row.children);

        operateLastLeve(row);

      } else if (levelSataus == 3) {

        operateLastLeve(row);

      }

    },
    // 检测表格数据是否全选
    checkIsAllSelect() {
      this.oneProductIsSelect = [];
      this.renderDynamic.forEach((item) => {
        this.oneProductIsSelect.push(item.isSelect);
      });
      //判断一级产品是否是全选.如果一级产品全为true,则设置为取消全选,否则全选

      let isAllSelect = this.oneProductIsSelect.every((selectStatusItem) => {
        return true == selectStatusItem;
      });
      return isAllSelect;
    },
    // 表格全选事件
    selectAllFun(selection) {
      let isAllSelect = this.checkIsAllSelect();

      this.renderDynamic.forEach((item) => {

        item.isSelect = isAllSelect;

        this.$refs.product.toggleRowSelection(item, !isAllSelect);

        this.selectFun(selection, item);

      });

    },
    // 表格行样式 当当前行的状态为不明确状态时,添加样式,使其复选框为不明确状态样式
    rowClassNameFun({row}) {
      if (row.isSelect === "") {
        return "indeterminate";
      }
    },
    // 表格标题样式 当一级目录有为不明确状态时,添加样式,使其全选复选框为不明确状态样式
    headerRowClassName({row}) {
      let oneProductIsSelect = [];

      this.renderDynamic.forEach((item) => {
        oneProductIsSelect.push(item.isSelect);
      });

      if (oneProductIsSelect.includes("")) {
        return "indeterminate";
      }

      return "";

    },
  }
}
</script>

<style lang='less'>
.indeterminate .el-checkbox__input .el-checkbox__inner {
  background-color: #409eff !important;
  border-color: #409eff !important;
  color: #fff !important;
}
.indeterminate .el-checkbox__input.is-checked .el-checkbox__inner::after {
  transform: scale(0.5);
}
.indeterminate .el-checkbox__input .el-checkbox__inner {
  background-color: #f2f6fc;
  border-color: #dcdfe6;
}
.indeterminate .el-checkbox__input .el-checkbox__inner::after {
  border-color: #c0c4cc !important;
  background-color: #c0c4cc;
}
.product-show th .el-checkbox__inner {
  display: none !important;
}
.indeterminate .el-checkbox__input .el-checkbox__inner::after {
  content: "";
  position: absolute;
  display: block;
  background-color: #fff;
  height: 2px;
  transform: scale(0.5);
  left: 0;
  right: 0;
  top: 5px;
  width: auto !important;
}
.product-show .el-checkbox__inner {
  display: block !important;
}
.product-show .el-checkbox {
  display: block !important;
}
</style>

搜索一下午资料 终于找到个完美的 赶紧记录一下

原文在此:ElementUI Table 表格树形结构多选框选中父级时会选中子级(递归多级) - FancyAnnaYL - 博客园 (cnblogs.com)

### el-table 树形数据勾实现方式 对于 `el-table` 的树形数据显示与勾功能,Element Plus 提供了一套完整的解决方案来处理复杂的数据结构。为了使表格能够展示并操作树状层次关系的数据,需设置特定属性。 #### 属性配置 - **row-key**: 设置每一行唯一标识符字段名,用于识别节点间的父子关系[^1]。 - **tree-props**: 定义子 children 字段名称,默认为 "children"。 - **default-expand-all**: 是否默认展开所有行,适用于初次加载时全部显示细节信息。 - **show-checkbox**: 显示框列,允许用户个条目。 当涉及到树形数据的择逻辑时,还需要考虑父节点与其子节点之间的联动效果: - 如果希望父节点被中则自动全选其下所有的子孙节点,则可以监听 `selection-change` 事件,在回调函数内遍历当前中的项,并手动调用 `toggleRowSelection(row, selected)` 来控制关联节点的状态变化。 下面是一个简单的例子展示了如何创建带有复框的可扩展树表单: ```html <template> <div> <el-table :data="tableData" style="width: 100%" row-key="id" default-expand-all show-checkbox @selection-change="handleSelectionChange"> <!-- 列定义 --> <el-table-column type="selection" width="55"></el-table-column> <el-table-column prop="name" label="Name"></el-table-column> ... </el-table> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; const tableData = [ { id: 1, name: 'Parent Node', children: [{ id: 2, name: 'Child Node' }] } ]; function handleSelectionChange(selection) { console.log('Selected:', selection); } </script> ``` 此代码片段实现了基本的功能需求,即通过指定 `row-key`, `tree-props` 及其他必要参数让 `el-table` 支持树型结构的同时提供复项让用户可以择任意数量的记录;并通过自定义的方法响应用户的交互行为,如点击某一行前面的小方块触发整个分支或者仅该叶子结点的状态改变。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值