表格单元行合并方法

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

问题描述

使用 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>

效果展示如下:

相关推荐
用户938515635073 分钟前
Type vs Interface:读完这篇就没有面试官能难倒你了
前端·面试·typescript
油丶酸萝卜别吃1 小时前
jquery-ajax.js 说明文档
前端·javascript·jquery
windliang1 小时前
Claude Code 源码分析(九):子 Agent 如何分叉、继续与回到父会话
前端·javascript·面试
柒和远方2 小时前
V063: TS 面试必考:interface 与 type 的四大差异,与 LLM Harness 的自动化择优
前端·javascript
半个落月2 小时前
React useRef 详解:DOM 引用、持久化值与 Worker 实例
前端·react.js
阿黎梨梨2 小时前
TypeScript 类型编程:从新手到 Harness 工程实践
前端
黄金决明子2 小时前
Vue3 + Vite 打包后打开空白?
前端
张龙6872 小时前
终端效率翻倍实战:fzf + zoxide + ripgrep + bat 组合拳,告别重复敲命令
前端
宿6742 小时前
vue3-env环境
前端·vue.js
蔬菜_2 小时前
前端转全栈-day5(数组、list、set)
java·前端·数据结构·list