antd table 可伸缩列 react-resizable 多表头实现

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} />
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容