要在 Element UI 的 `el-table` 中合并相同数据的单元格,主要依赖于 `span-method` 属性。该属性允许开发者自定义单元格的跨行或跨列显示逻辑。以下是详细的解决方案:
### 实现步骤
#### 1. 准备数据
假设我们有一组如下所示的数据:
```javascript
tableData: [
{ id: '1', name: '王小虎', amount1: '165', amount2: '3.2', amount3: 10 },
{ id: '1', name: '王小虎', amount1: '162', amount2: '4.43', amount3: 12 },
{ id: '1', name: '王we虎', amount1: '621', amount2: '1.9', amount3: 9 },
{ id: '2', name: '王we虎', amount1: '621', amount2: '2.2', amount3: 17 },
{ id: '3', name: '王小虎', amount1: '621', amount2: '4.1', amount3: 15 }
],
```
为了实现合并功能,我们需要遍历数据并计算每一列中连续相同的值的数量。
---
#### 2. 计算合并规则
创建一个方法用于生成合并所需的跨度数组。以下是一个示例函数:
```javascript
methods: {
getSpanArr(data) {
let spanArr = [];
data.forEach((item, index) => {
if (index === 0) {
spanArr.push(1);
} else {
if (data[index].id === data[index - 1].id && item.name === data[index - 1].name) {
spanArr[spanArr.length - 1]++;
spanArr.push(0);
} else {
spanArr.push(1);
}
}
});
return spanArr;
}
}
```
在此基础上,我们可以扩展到其他字段(如 `amount1`, `amount2` 等)。对于每列都需要类似的处理逻辑。
---
#### 3. 定义 `spanMethod`
在 `<el-table>` 组件中绑定 `span-method` 属性,并传入一个函数来控制单元格的合并行为。
```html
<el-table
:data="tableData"
border
style="width: 100%"
:span-method="objectSpanMethod">
</el-table>
```
对应的 JavaScript 方法如下:
```javascript
computed: {
objectSpanMethod() {
const spanArrId = this.getSpanArr(this.tableData.map(item => ({ id: item.id, name: item.name })));
const spanArrAmount1 = this.getSpanArr(this.tableData.map(item => item.amount1));
return function({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0 || columnIndex === 1) { // 假设第0列和第1列为需要合并的部分
const _row = spanArrId[rowIndex];
const _col = _row > 0 ? 1 : 0;
return { rowspan: _row, colspan: _col };
} else if (columnIndex === 2) { // 假设第2列为另一个需要合并的部分
const _row = spanArrAmount1[rowIndex];
const _col = _row > 0 ? 1 : 0;
return { rowspan: _row, colspan: _col };
}
};
}
},
```
在这里,`getSpanArr` 被多次调用以分别针对不同的列生成合并规则。最终通过 `objectSpanMethod` 返回具体的行列跨越配置。
---
#### 4. 渲染表格列
按照常规方式渲染表头即可。例如:
```html
<el-table-column prop="id" label="ID" width="80"></el-table-column>
<el-table-column prop="name" label="姓名" width="120"></el-table-column>
<el-table-column prop="amount1" label="金额1" width="120"></el-table-column>
<el-table-column prop="amount2" label="金额2" width="120"></el-table-column>
<el-table-column prop="amount3" label="金额3" width="120"></el-table-column>
```
---
### 示例代码总结
完整的 Vue 部分代码如下:
```javascript
export default {
data() {
return {
tableData: [
{ id: '1', name: '王小虎', amount1: '165', amount2: '3.2', amount3: 10 },
{ id: '1', name: '王小虎', amount1: '162', amount2: '4.43', amount3: 12 },
{ id: '1', name: '王we虎', amount1: '621', amount2: '1.9', amount3: 9 },
{ id: '2', name: '王we虎', amount1: '621', amount2: '2.2', amount3: 17 },
{ id: '3', name: '王小虎', amount1: '621', amount2: '4.1', amount3: 15 }
]
};
},
methods: {
getSpanArr(data) {
let spanArr = [];
data.forEach((item, index) => {
if (index === 0) {
spanArr.push(1);
} else {
if (JSON.stringify(data[index]) === JSON.stringify(data[index - 1])) {
spanArr[spanArr.length - 1]++;
spanArr.push(0);
} else {
spanArr.push(1);
}
}
});
return spanArr;
}
},
computed: {
objectSpanMethod() {
const spanArrIdName = this.getSpanArr(
this.tableData.map(item => ({ id: item.id, name: item.name }))
);
const spanArrAmount1 = this.getSpanArr(this.tableData.map(item => item.amount1));
return function({ row, column, rowIndex, columnIndex }) {
if ([0, 1].includes(columnIndex)) {
const _row = spanArrIdName[rowIndex];
const _col = _row > 0 ? 1 : 0;
return { rowspan: _row, colspan: _col };
} else if (columnIndex === 2) {
const _row = spanArrAmount1[rowIndex];
const _col = _row > 0 ? 1 : 0;
return { rowspan: _row, colspan: _col };
}
};
}
}
};
```
---
### 注意事项
- 数据需按一定顺序排列才能正确合并。如果原始数据无序,则应先对其进行排序。
- 当涉及多个字段时,可能需要额外的逻辑来区分哪些字段应该参与合并[^1]。
---