表格单元行合并方法

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

问题描述

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

效果展示如下:

相关推荐
dae bal44 分钟前
关于RSA和AES加密
前端·vue.js
柳杉1 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog1 小时前
低端设备加载webp ANR
前端·算法
LKAI.1 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy2 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js
前端工作日常2 小时前
我对eslint的进一步学习
前端·eslint
禁止摆烂_才浅3 小时前
VsCode 概览尺、装订线、代码块高亮设置
前端·visual studio code
程序员猫哥3 小时前
vue跳转页面的几种方法(推荐)
前端
代码老y4 小时前
十年回望:Vue 与 React 的设计哲学、演进轨迹与生态博弈
前端·vue.js·react.js
一条上岸小咸鱼4 小时前
Kotlin 基本数据类型(五):Array
android·前端·kotlin