element table 表格 span-method 某一列进行相同合并 支持树结构表格

须知

这是 vue2 版本,不过理论上 vue3 也能参考使用

可以直接打开 codepen 查看代码

效果图

在这里插入图片描述

代码

打不开 codepen 或者codepen 失效,查看下面代码参考

<script src="//unpkg.com/vue@2/dist/vue.js"></script>
<script src="//unpkg.com/element-ui@2.15.14/lib/index.js"></script>
<div id="app">
  <template>
    <div>
      <el-button @click="logMergedRowCount">Log</el-button>
      <el-table row-key="id" @expand-change="expandChange" :data="tableData" :span-method="objectSpanMethod" border :tree-props="{children: 'children', hasChildren: 'hasChildren'}" style="width: 100%; margin-top: 20px">
        <el-table-column prop="name" label="姓名">
        </el-table-column>
        <el-table-column prop="id" label="ID" width="180">
        </el-table-column>
        <el-table-column prop="amount1" label="数值 1(元)">
        </el-table-column>
        <el-table-column prop="amount2" label="数值 2(元)">
        </el-table-column>
        <el-table-column prop="amount3" label="数值 3(元)">
        </el-table-column>
      </el-table>
    </div>
  </template>
</div>
@import url("//unpkg.com/element-ui@2.15.14/lib/theme-chalk/index.css");

var Main = {
  data() {
    return {
      tableData: [],
      spanMap: {}, // 每层的 id => {子级有几个, 祖宗是谁}

      expandRowKeys: {}
    };
  },
  computed: {
    parentMap() {
      const keys = Object.entries(this.expandRowKeys)
        .filter(([k, v]) => v)
        .map(([k]) => k);
      console.log("keys", keys);
      let result = {};
      for (const item of keys) {
        const expandRow = this.spanMap[item];
        if (result[expandRow.parentId]) {
          result[expandRow.parentId] += expandRow.childCount;
        } else {
          result[expandRow.parentId] = expandRow.childCount;
        }
      }
      return result;
    }
  },
  mounted() {
    let datalist = [
      {
        id: "1",
        name: "一级事件",
        amount1: "165",
        amount2: "4.43",
        amount3: 12,
        children: [
          {
            id: "2",
            name: "二级事件1",
            amount1: "165",
            amount2: "4.43",
            amount3: 12,
            children: [
              {
                id: "3",
                name: "三级事件1",
                amount1: "165",
                amount2: "4.43",
                amount3: 12
              },
              {
                id: "4",
                name: "三级事件2",
                amount1: "165",
                amount2: "4.43",
                amount3: 12
              }
            ]
          },
          {
            id: "5",
            name: "二级事件2",
            amount1: "165",
            amount2: "4.43",
            amount3: 12
          }
        ]
      },
      {
        id: "6",
        name: "一级事件2",
        amount1: "165",
        amount2: "4.43",
        amount3: 12
      },
      {
        id: "7",
        name: "二级事件1",
        amount1: "165",
        amount2: "4.43",
        amount3: 12,
        children: [
          {
            id: "8",
            name: "三级事件1",
            amount1: "165",
            amount2: "4.43",
            amount3: 12
          },
          {
            id: "9",
            name: "三级事件2",
            amount1: "165",
            amount2: "4.43",
            amount3: 12
          }
        ]
      },
      {
        id: "10",
        name: "三级事件1",
        amount1: "165",
        amount2: "4.43",
        amount3: 12
      },
      {
        id: "11",
        name: "三级事件2",
        amount1: "165",
        amount2: "4.43",
        amount3: 12
      }
    ];
    datalist = this.preprocessData(datalist);
    this.tableData = datalist;
  },
  methods: {
    /**
     * 处理行展开状态变化的事件。
     * @param {Object} row - 当前行的数据对象。
     * @param {boolean} expanded - 表示行是否被展开。
     */
    expandChange(row, expanded) {
      // 使用 Vue 的 $set 方法更新展开行的键值对,确保响应性
      this.$set(this.expandRowKeys, row.id, expanded);
    },

    /**
     * 打印合并行数的日志。
     */
    logMergedRowCount() {
      // 打印合并行数的映射,用于调试或检查合并状态
      console.log(this.mergedRowCount);
    },

    preprocessData(data, id = "") {
      return data.map((item) => {
        const newItem = { ...item };
        newItem.parentId = id; // 将当前路径作为 parentId 属性
        if (this.spanMap[item.id]) {
          this.spanMap[item.id].childCount = item.children?.length || 0;
        } else {
          this.spanMap[item.id] = {
            childCount: item.children?.length || 0,
            parentId: id || item.id
          };
        }
        if (item.children && item.children.length > 0) {
          newItem.children = this.preprocessData(item.children, id || item.id);
        }
        return newItem;
      });
    },
    //进行表格合并
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 1) {
        if (row.parentId) {
          return {
            rowspan: 0,
            colspan: 0
          };
        } else {
          console.log("row.id", this.parentMap[row.id]);
          return {
            rowspan: (this.parentMap[row.id] ?? 0) + 1,
            colspan: 1
          };
        }
      }
    }
  }
};
var Ctor = Vue.extend(Main);
new Ctor().$mount("#app");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泡泡码客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值