react + antd 实现表格拖拽调整列宽

前言

正常来讲其实表格拖拽调整列宽这个需求比较合理,说常见吧到也不见得😅,毕竟一般表格在设置时各列已经基本定好,但是.....总有那几个人不想走寻常路,非要拖拽调整列宽,谁叫人家是甲方大大呢🙄,下面就是结合网上查询和实践证明的亲身经历

第一步

安装 react-resizable 插件

npm install --save react-resizable

第二步

新建一个 ResizableTitle.js 的文件

import{ Resizable }from 'react-resizable';
import React,{ useState }from 'react';

const ResizableTitle = (props) => {
    const{ onResize, width, ...restProps }= props;
    const [offset, setOffset] = useState(0);
    if(!width){
        return <th {...restProps}/>;
    }
    return (
        <Resizable
            width={Number(width) + Number(offset)}
            height={0}
            handle={
                <span 
                    className="react-resizable-handle"
                    style={{ transform: "translateX(${offset}px)"}}
                    onClick={e => {
                        e.stopPropagation();
                        e.preventDefault();
                    }}
                />
            }
            onResizeStart={() => {
                document.body.onselectstart = () => false;
            }}
            onResize={(e, { size }) => {
                // 设置最小宽度,防止列被隐藏
                const newWidth = size.width < 75 ? 75 : size.width;
                setOffset(newWidth - width);
            }}
            onResizeStop={(...arg) => {
                document.body.onselectstart = () => true;
                setOffset(0);
                onResize(...arg)
            }}
            draggableOpts={{
                enableUserSelectHack: false
            }}
        >
            <th
                {...restProps}
                style={{
                    overflow: "visible",
                    ...restProps.style
                }}
            >
               <div
                    style={{
                        width: "100%",
                        overflow: "hidden",
                        whiteSpace: "nowrap",
                        textOverflow: "ellipsis"
                    }}
                >
                    {restProps.children}
                </div> 
            </th>
        </Resizable>
    )
}

export default ResizableTitle

第三步

在表格组件中引用,代码如下:

import Reat,{ useMemo, useState } from 'react';
import ResizableTitle from './ResizableTitle'
import cloneDeep from 'lodash/cloneDeep';

function DetailPage() {
    const [columns, setColumns] = useState([])
    const handleResize = info => (e, { size }) => {
        setColumns((values)=> {
            values.map(item => {
                if(item.dataIndex === info.dataIndex) {
                    retrun {
                        ...item,
                        width: size.width
                    }
                } else {
                    retrun item
                }
            })
        })
    }
    
    const columnsList = useMemo(() => {
        return columns.map(col => {
            return {
                ...col,
                onHeaderCell: (column) => {
                    width: column.width,
                    onResize: handleResize(col)
                }
            }
        })
    }, [columns])
    
    return (
        <Table
            rowKey="id"
            loading="loading"
            components={{
                header: {
                    cell: ResizableTitle     
                }
            }}
            pagination={{
                current: params.current.pageNum,
                pageSize: params.current.pageSize,
                total: dataSource.total,
            }}
            dataSource={dataSource.list}
            columns={columnsList}
        />
    )
}

export default React.memo(DetailPage)

注意事项

使用 react-resizable 插件时要引入包中的 style.css 文件,或者粘贴至自己的 css 中引用,否则不显示拖拽图标。

.react-resizable {
    position: relative;
    background-clip: padding-box;
}

.react-resizable-handle {
    position: absolute;
    right: 0;
    bottom: 0;
    z-index: 100;
    width: 10px;
    height: 100%;
    border-right: solid 1px #40a9ff;
    cursor: col-resize;
}

 

posted @ 2022-06-30 22:42  蹦跶的比丢  阅读(3585)  评论(3编辑  收藏  举报