antd 的表格组件的列宽,是通过width属性去初始化的,有时候渲染的内容不固定,这个宽做不到通用所以研究怎么实现表格列宽拖动,主要的实现步骤如下:
- 使用table的components API修改表格头部为
react-resizable
提供的组件- 并在columns设置侦听函数,用于动态修改宽度 (onHeaderCell API)
- 还需要设置css,让控制组件显示在正确位置
在实际的应用中,Table组件直接再次封装为可以拖动的组件供所有人使用,而且拖动后的布局是可以本地存储的,或者用接口去存也是一样,实现效果如下
下面是实现的具体代码,封装了一个MyTable 组件,在这个组件中可以自定义antd Table组件的交互样式等
1、安装插件
npm install react-resizable
2、写MyTable组件
目录结构
这里使用了.tsx 来写,里面的校验随便写的 方便大家看,同文件夹下的ResizableTitle.tsx
文件就是自定义的表头,通过antd Table组件的components重写表格,每次拖动中不断更新表格的布局不断渲染,看起来就是一个连续的过程
// Mytable/index.tsx
import { Table } from 'antd';
import { useState } from 'react';import ResizableTitle from './ResizableTitle'
import './index.css'export default function MyTable(){const [columns, setColumns] = useState([{title: 'Date',dataIndex: 'date',width: 200,},{title: 'Amount',dataIndex: 'amount',width: 100,sorter: (a, b) => a.amount - b.amount,},{title: 'Type',dataIndex: 'type',width: 100,},{title: 'Note',dataIndex: 'note',width: 100,},{title: 'Action',key: 'action',render: () => <a>Delete</a>,},]);const dataSource = [{key: 0,date: '2018-02-11',amount: 120,type: 'income',note: 'transfer',},{key: 1,date: '2018-03-11',amount: 243,type: 'income',note: 'transfer',},{key: 2,date: '2018-04-11',amount: 98,type: 'income',note: 'transfer',},];const mergeColumns:any = columns.map((col, index) => {return {...col,onHeaderCell: (column:any) => ({width: column.width,onResize: (_:any, { size }: any) => {const newColumns = [...columns];newColumns[index] = {...newColumns[index],width: size.width,};setColumns(newColumns);},}),}});return (<Tablecomponents={{header: {cell: ResizableTitle,},}}columns={mergeColumns}dataSource={dataSource}/>);
}
// Mytable/ResizableTitle.tsx
import { Resizable } from 'react-resizable';export default function ResizableTitle(props:any){const { onResize, width, ...restProps } = props;return (! width ?<th {...restProps} />: <Resizablewidth={width}height={0}handle={<spanclassName="react-resizable-handle"onClick={e => {e.stopPropagation();}}/>}onResize={onResize}draggableOpts={{ enableUserSelectHack: false }}><th {...restProps} /></Resizable>);
};
/* Mytable/index.css */
.react-resizable { position: relative;background-clip: padding-box;} .react-resizable-handle { position: absolute;right: -5px;bottom: 0;z-index: 1;width: 10px;height: 100%;cursor: col-resize;}
3、其他说明
作者在使用该方法的时候遇到性能不佳,出现了明显的卡顿现象,一时没查到原因,因为是在业务组件中使用,表格非常大,而且有很多其他的渲染,电脑的性能也有限,卡成了PPT,作了以下调整,下面是简单的讲解这个过程:
- 不再使用mergeColumns,不停的去渲染Table组件,每次只与普通表格一样只渲染一次
- 直接操作DOM,在onResize中找到计算鼠标拖动的距离,通过类名的形式找到table 的布局器并改变宽度