antd 自带的可伸缩列控制列宽,不能对多表头、合并单元格的table起效果,于是优化了一下
奉上截图2张,没有录屏
拖动前.png
拖动后.png
ResizableTable .tsx 组件代码如下
import {Table} from "antd4"
import {ColumnsType, TableProps} from "antd/lib/table"
import React, {useEffect, useState} from "react"
import {Resizable} from "react-resizable"
import "./resizableTable.less"
type TResizableTable = {
column: ColumnsType<any>
data: TableProps<any>["dataSource"]
}
/**
* 可伸缩列
* @param props
* @returns
*/
const ResizableTable = (props: TResizableTable) => {
const [column, setcolumn] = useState<ColumnsType<any>>([])
useEffect(() => {
if (props.column) {
setcolumn(props.column)
}
}, [props.column])
//给每一列加onResize 用于拖拽
const setNewColumnCell = (column: any[], indexarray: number[]) => {
column.map((col, index) => {
let array2 = JSON.parse(JSON.stringify(indexarray))
array2.push(index)
col.onHeaderCell = (column: {width: any}) => ({
width: column.width ?? 0,
onResize: handleResize(index, array2)
})
if (col.children?.length) {
setNewColumnCell(col.children, array2)
}
})
}
const handleResize = (index: number, indexarray: number[]) => (e: any, a: {size: any}) => {
const {size} = a
let nextColumns =JSON.parse(JSON.stringify(column))
const width = size?.width ?? 80
setNewColumnWidth(nextColumns, indexarray, width, [])
setcolumn(nextColumns)
}
const setNewColumnWidth = (column: any[], indexarray: number[], width: number, nowIndex: number[]) => {
let i = 0
for (let col of column) {
const index = i
i++
const currentLevel = indexarray?.[nowIndex.length]
if (currentLevel == index) {
console.log("当前层级", index, indexarray)
let array2 = JSON.parse(JSON.stringify(nowIndex))
array2.push(index)
if (JSON.stringify(array2) == JSON.stringify(indexarray)) {
col.width = width
break
}
if (col.children?.length) {
setNewColumnWidth(col.children, indexarray, width, array2)
}
}
}
}
const newcolumn = JSON.parse(JSON.stringify(column))
setNewColumnCell(newcolumn, [])
console.log(newcolumn, "newcolumn")
// setlastColumn(newcolumn)
return (
<Table
bordered
components={{
header: {
cell: ResizableTitle
}
}}
size="small"
scroll={{x: "100vw"}}
columns={newcolumn}
dataSource={props.data}
/>
)
}
export default ResizableTable
const ResizableTitle = (props: any) => {
const {onResize, width, ...restProps} = props
if (!width) {
return <th {...restProps} />
}
return (
<Resizable
width={width}
height={0}
handle={
<span
className="react-resizable-handle"
onClick={(e) => {
e.stopPropagation()
}}
/>
}
onResize={onResize}
draggableOpts={{enableUserSelectHack: false}}
>
<th {...restProps} />
</Resizable>
)
}
resizableTable.less
:global {
.react-resizable {
position: relative;
background-clip: padding-box;
}
.react-resizable-handle {
position: absolute;
width: 10px;
height: 100%;
bottom: 0;
right: -5px;
cursor: col-resize;
background-image: none;
z-index: 1;
}
}
使用方法
const ResettlementsColumn: = [
{
title: "人口",
key: "人口",
children: [
{
title: "小计",
dataIndex: "Population",
width: 100,
ellipsis: true
},
{
title: "农业",
dataIndex: "CityPopulation",
width: 100,
ellipsis: true
},
{
title: "非农",
dataIndex: "VillagePopulation",
width: 100,
ellipsis: true
}
]
},
{
title: "地区",
dataIndex:"area"
}
]
const data = [
{ Population: "1", CityPopulation: 0, VillagePopulation: 1 }
]
<ResizableTable column={ResettlementsColumn} data={data} />