记录一下实际开发时候所用到的表格单元行合并方法。
问题描述
使用 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>
效果展示如下:
