表格单元行合并方法

记录一下实际开发时候所用到的表格单元行合并方法。

问题描述

使用 el-table 表格时候在某几列需要实现上下合并单元行,比如表头是电厂,机组,还有一些机组的配置,电厂包含多个机组,机组包含多个配置,此时电厂和机组就需要合并单元行。

原先表格展示如下:

可以看到一个电厂下有很多个机组,一个机组下有多个配置,所以电厂和机组都需要去进行合并单元行。

合并电厂单元行

先去创建一个电厂的数组,和一个电厂的索引。

js 复制代码
  data() {
    return {
      // 表格数据
      tableData: [...],
      // 电厂数组
      spanArr_plant: [],
      // 电厂索引
      pos_plant: 0,
    };
  },

处理数据的方法:

js 复制代码
// 初始化电厂数组和电厂索引数据
this.spanArr_plant = [];
this.pos_plant = 0;
for (let i = 0; i < this.tableData.length; i++) {
  if (i === 0) {
    // 此时电厂数组为[1],表示当前电厂有一行数据
    this.spanArr_plant.push(1);
    // 此时电厂索引为0,表示的就是[1]中当前电厂所在索引
    this.pos_plant = 0;
  } else {
    // 判断当前行数据中电厂信息与上一行数组电厂信息是否相同
    if (this.tableData[i]["plant"] === this.tableData[i - 1]["plant"]) {
      // 如果相同,电厂数组里的电厂索引位置+1,表示电厂相同的数据多了一行
      this.spanArr_plant[this.pos_plant] += 1;
      // 电厂数组再push一个0
      this.spanArr_plant.push(0);
      // 此时电厂数组就是[2,0],表示的就是电厂相同的数据目前有两行,如果下一项还相同的话,就是[3,0,0]
    } else {
      // 如果下一行数据的电厂信息和上一行数据电厂信息不相同,电厂数据就重新push一个1,代表有新的电厂,然后电厂索引也改为这个新电厂在电厂数组的索引
      this.spanArr_plant.push(1);
      this.pos_plant = i;
    }
  }
}

然后就是el-table自带的合并单元行的方法:

html 复制代码
    <el-table
      :data="tableData"
      border
      stripe
      height="100%"
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      :span-method="objectSpanMethod"
    >
      <el-table-column label="电厂" prop="plant"></el-table-column>
      <el-table-column label="机组" prop="unit"></el-table-column>
      <el-table-column label="配置" prop="configuration"></el-table-column>
    </el-table>
js 复制代码
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      // 电厂是第一列,所以判断columnIndex === 0
      if (columnIndex === 0) {
        const _row = this.spanArr_plant[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return [_row, _col];
      }
    },

效果展示:

合并电厂单元行和机组单元行

这里不能光合并一个电厂的单元行,还有机组的单元行,但是这里注意一下,这里不是说跟合并电厂单元行一样再重复一遍机组的就好了,这里的机组合并的前提是电厂也得一样。

首先还是先创建一个机组数据和机组索引:

js 复制代码
  data() {
    return {
      // 表格数据
      tableData: [...],
      // 电厂数组
      spanArr_plant: [],
      // 电厂索引
      pos_plant: 0,
      // 机组数组
      spanArr_unit: [],
      // 机组索引
      pos_unit: 0,
    };
  },

处理数据的方法:

js 复制代码
// 初始化数组和索引数据
this.spanArr_plant = [];
this.pos_plant = 0;
this.spanArr_unit = [];
this.pos_unit = 0;
for (let i = 0; i < this.tableData.length; i++) {
  if (i === 0) {
    this.spanArr_plant.push(1);
    this.pos_plant = 0;
    // 跟电厂一样的操作
    this.spanArr_unit.push(1);
    this.pos_unit = 0;
  } else {
    if (this.tableData[i]["plant"] === this.tableData[i - 1]["plant"]) {
      this.spanArr_plant[this.pos_plant] += 1;
      this.spanArr_plant.push(0);

      // 在电厂相同的时候进行跟电厂一样的判断
      if (this.tableData[i]["unit"] === this.tableData[i - 1]["unit"]) {
        this.spanArr_unit[this.pos_unit] += 1;
        this.spanArr_unit.push(0);
      } else {
        this.spanArr_unit.push(1);
        this.pos_unit = i;
      }
    } else {
      this.spanArr_plant.push(1);
      this.pos_plant = i;
      // 电厂不相同的时候也是进行跟电厂一样的操作
      this.spanArr_unit.push(1);
      this.pos_unit = i;
    }
  }
}

然后就是el-table自带的合并单元行的方法:

html 复制代码
    <el-table
      :data="tableData"
      border
      stripe
      height="100%"
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      :span-method="objectSpanMethod"
    >
      <el-table-column label="电厂" prop="plant"></el-table-column>
      <el-table-column label="机组" prop="unit"></el-table-column>
      <el-table-column label="配置" prop="configuration"></el-table-column>
    </el-table>
js 复制代码
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        const _row = this.spanArr_plant[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return [_row, _col];
      }
      // 机组为第二列所以判断columnIndex === 1
      if (columnIndex === 1) {
        const _row = this.spanArr_unit[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return [_row, _col];
      }
    }

全部代码如下:

html 复制代码
<template>
  <div class="screen-view">
    <el-table
      :data="tableData"
      border
      stripe
      height="100%"
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      :span-method="objectSpanMethod"
    >
      <el-table-column label="电厂" prop="plant"></el-table-column>
      <el-table-column label="机组" prop="unit"></el-table-column>
      <el-table-column label="配置" prop="configuration"></el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          plant: "电厂1",
          unit: "机组1",
          configuration: "配置1",
        },
        {
          plant: "电厂1",
          unit: "机组1",
          configuration: "配置2",
        },
        {
          plant: "电厂1",
          unit: "机组1",
          configuration: "配置3",
        },
        {
          plant: "电厂1",
          unit: "机组2",
          configuration: "配置1",
        },
        {
          plant: "电厂1",
          unit: "机组2",
          configuration: "配置2",
        },
        {
          plant: "电厂2",
          unit: "机组1",
          configuration: "配置1",
        },
        {
          plant: "电厂2",
          unit: "机组1",
          configuration: "配置2",
        },
        {
          plant: "电厂2",
          unit: "机组2",
          configuration: "配置1",
        },
        {
          plant: "电厂2",
          unit: "机组2",
          configuration: "配置2",
        },
        {
          plant: "电厂2",
          unit: "机组2",
          configuration: "配置3",
        },
      ],
      // 电厂数组
      spanArr_plant: [],
      // 电厂索引
      pos_plant: 0,
      // 机组数组
      spanArr_unit: [],
      // 机组索引
      pos_unit: 0,
    };
  },
  created() {
    this.init();
  },
  methods: {
    init() {
      this.spanArr_plant = [];
      this.pos_plant = 0;
      this.spanArr_unit = [];
      this.pos_unit = 0;
      for (let i = 0; i < this.tableData.length; i++) {
        if (i === 0) {
          this.spanArr_plant.push(1);
          this.pos_plant = 0;
          this.spanArr_unit.push(1);
          this.pos_unit = 0;
        } else {
          if (this.tableData[i]["plant"] === this.tableData[i - 1]["plant"]) {
            this.spanArr_plant[this.pos_plant] += 1;
            this.spanArr_plant.push(0);

            if (this.tableData[i]["unit"] === this.tableData[i - 1]["unit"]) {
              this.spanArr_unit[this.pos_unit] += 1;
              this.spanArr_unit.push(0);
            } else {
              this.spanArr_unit.push(1);
              this.pos_unit = i;
            }
          } else {
            this.spanArr_plant.push(1);
            this.pos_plant = i;
            this.spanArr_unit.push(1);
            this.pos_unit = i;
          }
        }
      }
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        const _row = this.spanArr_plant[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return [_row, _col];
      }
      if (columnIndex === 1) {
        const _row = this.spanArr_unit[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return [_row, _col];
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.screen-view {
  box-sizing: border-box;
  padding: 10px;
  height: 100%;
}
</style>

效果展示如下:

相关推荐
Eric.4617 分钟前
Wan‑Animate+MiniMax-H3 本地部署 AI 漫剧流水线:8G 显存动作迁移与动态分镜工程实战
前端·人工智能·comfyui·ai漫剧
库拉镜像AI牛牛2 小时前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别
律宏阔2 小时前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
行者全栈架构师2 小时前
【鸿蒙心迹】相册文搜图工程化落地:HarmonyOS 7.0 端侧 AI 检索全链路实战与 5 个踩坑解法
前端
律宏阔2 小时前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
Seraphina362 小时前
DVWA(XSS Reflected/Stored High,CSRF Low)
前端·xss·csrf
默_笙3 小时前
🍔 中间件不只是打日志:四个钩子、一次短路,和自带的工具
前端·javascript
程序员老赵4 小时前
Docker 部署 Dolibarr:轻松搭建开源 ERP/CRM 平台
运维·前端·后端
星禾元亨4 小时前
同一件事有三份资料,AI 该信哪一份?冲突判定、优先级链与处置流程
前端·人工智能
Dovis(誓平步青云)4 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑