表格单元行合并方法

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

问题描述

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

效果展示如下:

相关推荐
写代码的小王吧1 小时前
【安全】Web渗透测试(全流程)_渗透测试学习流程图
linux·前端·网络·学习·安全·网络安全·ssh
小小小小宇2 小时前
CSS 渐变色
前端
snow@li2 小时前
前端:开源软件镜像站 / 清华大学开源软件镜像站 / 阿里云 / 网易 / 搜狐
前端·开源软件镜像站
小小小小宇3 小时前
配置 Gemini Code Assist 插件
前端
one 大白(●—●)3 小时前
前端用用jsonp的方式解决跨域问题
前端·jsonp跨域
刺客-Andy3 小时前
前端加密方式 AES对称加密 RSA非对称加密 以及 MD5哈希算法详解
前端·javascript·算法·哈希算法
前端开发张小七3 小时前
13.Python Socket服务端开发指南
前端·python
前端开发张小七3 小时前
14.Python Socket客户端开发指南
前端·python
ElasticPDF-新国产PDF编辑器4 小时前
Vue 项目 PDF 批注插件库在线版 API 示例教程
前端·vue.js·pdf
拉不动的猪4 小时前
react基础2
前端·javascript·面试