elementUi 或 elementPlus 中 el-table 表格动态合并单元格
...大约 3 分钟
elementUi 或 elementPlus 中 el-table 表格动态合并单元格
背景
el-table 中,对于表格单元格的合并,文档中有介绍。原理就是通过设置span-method
方法,返回一个二维数组,数组中的每一项表示一行中每个单元格的合并情况。
但是这种方法针对已知表格中的某些单元格需要合并的情况,如果需要合并的单元格位置是动态的,那么这种方法就需要改造下了。
1、合并静态单元格(已知某几行、或某几列需要合并)
<template>
<div>
<el-table :data="tableData" :span-method="objectSpanMethod" border style="width: 100%; margin-top: 20px">
<el-table-column prop="id" label="ID" width="180" />
<el-table-column prop="name" label="Name" />
<el-table-column prop="amount1" label="Amount 1" />
<el-table-column prop="amount2" label="Amount 2" />
<el-table-column prop="amount3" label="Amount 3" />
</el-table>
</div>
</template>
<script setup>
//重点就是这个方法,返回一个数组,用来描述每行每个单元格的合并情况
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
if (columnIndex === 0) {
if (rowIndex % 2 === 0) {
return {
rowspan: 2,
colspan: 1
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
}
const tableData = [
{
id: '12987122',
name: 'Tom',
amount1: '234',
amount2: '3.2',
amount3: 10
},
{
id: '12987123',
name: 'Tom',
amount1: '165',
amount2: '4.43',
amount3: 12
},
{
id: '12987124',
name: 'Tom',
amount1: '324',
amount2: '1.9',
amount3: 9
},
{
id: '12987125',
name: 'Tom',
amount1: '621',
amount2: '2.2',
amount3: 17
},
{
id: '12987126',
name: 'Tom',
amount1: '539',
amount2: '4.1',
amount3: 15
}
]
</script>
2、合并动态单元格(某几行、或某几列需要合并,合并情况未知)
<template>
<div>
<el-table :data="tableData" :span-method="objectSpanMethod" border style="width: 100%; margin-top: 20px">
<el-table-column prop="id" label="ID" width="180" />
<el-table-column prop="name" label="Name" />
<el-table-column prop="amount1" label="Amount 1" />
<el-table-column prop="amount2" label="Amount 2" />
<el-table-column prop="amount3" label="Amount 3" />
</el-table>
</div>
</template>
<script setup>
// 需要通过这个方法,处理表格数据,返回一个数组,用来描述每行每个单元格的合并情况
// 判断是根据同一列中,相邻的行中数据相同,就进行合并
// 这个方法目前只是对行进行了合并,如果需要对列进行合并,需要修改这个方法
const getSpanArr = () => {
for (let i = 0; i < tableData.length; i++) {
let row = i
// let col = i % this.colCount;
if (row === 0) {
// i 表示行 j表示列
for (let j = 0; j < colFields.length; j++) {
spanArr[i * colFields.length + j] = {
rowspan: 1,
colspan: 1
}
}
} else {
for (let j = 0; j < colFields.length; j++) {
// 当前和上一次的一样
// 同一列,合并所有行的相同数据单元格
// 这个地方的判断条件可以进行修改,比如目前我就只希望针对第一列进行合并判断
if (tableData[row][colFields[j]] === tableData[row - 1][colFields[j]] && colFields[j] == 'pointIndicator') {
// beforeItem相当于一个中间变量
let beforeItem = spanArr[(row - 1) * colFields.length + j]
spanArr[row * colFields.length + j] = {
rowspan: 1 + beforeItem.rowspan, // 合并几行
colspan: 1 // 合并几列,我这里只是跨行合并,不跨列合并,所以用的1
}
beforeItem.rowspan = 0
beforeItem.colspan = 0
} else {
// rowspan 和 colspan 都为1表格此单元格不合并
spanArr[row * colFields.length + j] = {
rowspan: 1,
colspan: 1
}
}
}
}
}
// 对数据进行倒序
let stack = []
for (let i = 0; i < colFields.length; i++) {
for (let j = 0; j < tableData.length; j++) {
// i 表示列 j表示行
if (j === 0) {
if (spanArr[j * colFields.length + i].rowspan === 0) {
stack.push(spanArr[j * colFields.length + i])
}
} else {
if (spanArr[j * colFields.length + i].rowspan === 0) {
stack.push(spanArr[j * colFields.length + i])
} else {
stack.push(spanArr[j * colFields.length + i])
while (stack.length > 0) {
let pop = stack.pop()
let len = stack.length
spanArr[(j - len) * colFields.length + i] = pop
}
}
}
}
}
}
//重点就是这个方法,返回一个数组,用来描述每行每个单元格的合并情况
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
return spanArr[rowIndex * colFields.length + columnIndex]
}
// 存放表头字段
const colFields = ['pointIndicator', 'indicatorContent', 'indicatorScore', 'userScore']
const spanArr = reactive([]) //存储合并单元格的开始位置
const tableData = [
{
id: '12987122',
name: 'Tom',
amount1: '234',
amount2: '3.2',
amount3: 10
},
{
id: '12987123',
name: 'Tom',
amount1: '165',
amount2: '4.43',
amount3: 12
},
{
id: '12987124',
name: 'Tom',
amount1: '324',
amount2: '1.9',
amount3: 9
},
{
id: '12987125',
name: 'Tom',
amount1: '621',
amount2: '2.2',
amount3: 17
},
{
id: '12987126',
name: 'Tom',
amount1: '539',
amount2: '4.1',
amount3: 15
}
]
onMounted(() => {
// 如果是接口获取的数据,可以在接口返回数据后,先赋值给tableData,再调用getSpanArr(),然后再显示表格,否则可能会异常
getSpanArr()
})
</script>