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;
}