用法说明
处理表格单元格合并是很常见的开发需求,el-table官方提供了合并单元格的用法 如下:
根据使用说明很容易写出带有一堆if else 叠加的屎,随着合并条件的嵌套更会屎上加屎
javascript
const arraySpanMethod = ({
row,
column,
rowIndex,
columnIndex,
}) => {
if (rowIndex % 2 === 0) {
if (columnIndex === 0) {
return [1, 2]
} else if (columnIndex === 1) {
return [0, 0]
}
}
}
来看看哥们的究极无敌解决方案
先从案例说起,代码实现放在最后了,下面是一个很简单的表格,数据结构也列出来了。
javascript
const tableData = [
{
id: '12987122',
species:'人类',
gender:'男',
age:'10-20',
name: 'Tom1',
amount1: '234',
amount2: '3.2',
amount3: 10,
},
{
id: '12987123',
species:'人类',
gender:'男',
age:'10-20',
name: 'Tom1',
amount1: '165',
amount2: '4.43',
amount3: 12,
},
//....
]
现在我们按照物种这个维度将物种这一列进行行合并
使用我的合并方案只需要写出如下代码
vue
<template>
<el-table :data="tableData" :span-method="spanMethod">
//...
</el-table>
</template>
<script setup>
//...
const spanMethod = rowSpan(tableData,'species',['species'])
</script>
简简单单一行代码搞定,牛逼坏了。
rowSpan
接收三个参数
- 表格数据项
- 第二个参数代表合并的参照维度,如当前例子中传入的
'species'
,表示表格数据中'species'
字段相同的数据项应该被合并 - 第三个参数用于指定合并单元格被应用于哪一列上
接下来上点强度,此时产品经理提出,所有物种为"人类"的【Amount 1】取值都是234 我们需要按照物种维度,将【Amount 1】这一列进行合并
我们的代码仅仅只需改动一下第三个参数,将单元格合并应用到amount1
这一列就行了
js
const spanMethod = rowSpan(tableData,'species',['amount1'])
如果要同时合并,species
和amount1
,只需要在数组中同时包含这两个字段就ok
js
const spanMethod = rowSpan(tableData,'species',['amount1','species'])
继续上强度
为了说明问题,我们稍微调整下表格数据,新增两条数据
这时候产品的需求是:按照物种,进行性别的单元格合并,也就是说,进行性别单元格合并的前提是他们属于同一物种。
还是一行代码搞定,这时候我们只需要简单的修改一下第二个参数即可
js
const spanMethod = rowSpan(tableData,'species.gender',['gender'])
参数很直观,没什么好解释的,如果前提条件不断的堆叠,只需要按照这种格式往后面.
就完事。
再上强度,此时,除了性别以外,相同物种的单元格也要进行合并。
兵来将挡,再祭出一个杀器,添加一个高阶函数combie即可,具体实现稍后给出。
js
const spanMethod = combine(
rowSpan(tableData,'species.gender',['gender']),
rowSpan(tableData,'species',['species'])
)
函数实现
需要依赖lodash的groupBy,有需要请自行安装,或者自己手写实现。
rowSpan
js
import {groupBy} from 'lodash';
const rowSpan = (list, spanPath, columnNames) => {
const rowSpanHandler = (list, handledSpanPath) => {
if (!handledSpanPath) {
return
}
const spanPathList = handledSpanPath.split('.').filter(Boolean)
const fieldName = spanPathList.shift()
const groups = Object.values(groupBy(list , fieldName))
groups.forEach((group) => {
group.forEach((item, index) => {
if (spanPathList.length === 0) {
const resultPath = spanPath.split('.').join('_')
if (index === 0) {
item[`span_${resultPath}`] = [group.length, 1]
} else {
item[`span_${resultPath}`] = [0, 0]
}
} else {
rowSpanHandler(group, spanPathList.join('.'))
}
})
})
}
rowSpanHandler(list, spanPath)
return ({ row, column }) => {
if (columnNames.includes(column.property)) {
return row[`span_${spanPath.split('.').join('_')}`]
}
}
}
combine
js
const combine = (...funcArr)=>{
return ({ row, column })=>funcArr.map(item=>item({row, column})).find(Boolean)
}
结语
整篇文章只介绍了单元格的纵向合并,有需要的请参照贴出来的代码自行实现。