表格自动合并相同内容的单元格
合并hooks
import { TableColumnProps } from 'antd'
export const useAutoMergeTableCell = <T extends object>(
dataSource: Array<T>,
columns: Array<TableColumnProps> | Array<keyof T>
): Map<keyof T, Array<number>> => {
const cellToIndexMap = new Map<keyof T, Array<number>>()
const countInfoMap = new Map<keyof T, { startIndex: number; count: number; value: any } | null>()
const length = dataSource.length
const parseColumns = columns.map((m) => {
if (typeof m === 'string') {
return {
dataIndex: m
}
}
return m
})
parseColumns.forEach((it) => {
cellToIndexMap.set(it.dataIndex as keyof T, new Array(length).fill(0))
countInfoMap.set(it.dataIndex as keyof T, null)
})
const updateCellCount = (key: string) => {
const countInfo = countInfoMap.get(key as keyof T)
const indexArray = cellToIndexMap.get(key as keyof T)
indexArray![countInfo!.startIndex] = countInfo!.count
}
const calculateCount = (key: string, value: any, index: number) => {
const countInfo = countInfoMap.get(key as keyof T)
if (countInfo === null) {
countInfoMap.set(key as keyof T, { startIndex: index, count: 1, value })
} else {
if (countInfo!.value === value) {
countInfo!.count++
} else {
updateCellCount(key)
countInfoMap.set(key as keyof T, { startIndex: index, count: 1, value })
}
}
if (index === length - 1) {
updateCellCount(key)
}
}
for (let i = 0; i < length; ++i) {
parseColumns.forEach((column) => {
const key = column.dataIndex as string
calculateCount(key, Reflect.get(dataSource[i], key), i)
})
}
return cellToIndexMap
}
使用
让所有的列都进行单元格合并
// dataSource 用自己表格的数据
// columns 为你定义的列
const cellToIndexMap = useAutoMergeTableCell(dataSource, columns)
const parseColumns = columns.map((m) => {
return {
...m,
onCell: (_, index) => {
const indexArray = cellToIndexMap.get(m.dataIndex as keyof T)
return {
rowSpan: indexArray![index!] ?? 1
}
}
} as TableColumnProps
return m
})
只想部分列进行合并
只需要传递对应的想要合并的 key
即可
const cellToIndexMap = useAutoMergeTableCell(dataSource, ['key1', 'key2'])
const parseColumns = columns.map((m) => {
return {
...m,
onCell: (_, index) => {
const indexArray = cellToIndexMap.get(m.dataIndex as keyof T)
return {
rowSpan: indexArray![index!] ?? 1
}
}
} as TableColumnProps
return m
})
关于element-ui
如果想要适配于 element-ui
,只需要把 hooks
中的 dataIndex
替换为 prop
即可。
使用:
const cellToIndexMap = useAutoMergeTableCell(dataSource, ['key1', 'key2'])
// or
// const cellToIndexMap = useAutoMergeTableCell(dataSource, columns)
spanMethods ({ row, column, rowIndex, columnIndex }) {
const indexArray = cellToIndexMap.get(column.prop)
return {
rowSpan: indexArray![index!] ?? 1
colspan: 1
}
}