技术背景
本方案将演示如何构建可复用的高阶ProTable表格列拖拽组件,并提供完整的样式优化指南。
技术实现路径
1. 环境准备
csharp
# 使用任意包管理器安装核心依赖
yarn add react-resizable
# 或
npm install react-resizable --save
2. 构建高阶组件
创建ResizableTable.jsx
实现拖拽逻辑封装:
ini
import React, { useEffect, useState } from 'react';
import { Resizable } from 'react-resizable';
import { ProTable } from '@ant-design/pro-components';
import './index.less';
/**
* 可伸缩表头单元格组件
* @param {Object} props - 组件属性
* @param {Function} props.onResize - 列宽调整时的回调函数
* @param {number} props.width - 列的宽度
*/
const ResizableTitle = (props) => {
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();
e.preventDefault();
}}
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
<th {...restProps} />
</Resizable>
);
};
/**
* ProTable 可伸缩列组件
* @param {Object} props - ProTable 的属性
* @param {Array} props.columns - 表格列配置
*/
const ResizableTable = (props) => {
const [columns, setColumns] = useState([]);
// 当传入的 columns 发生变化时,更新本地 columns 状态
useEffect(() => {
if (props.columns) {
setColumns(props.columns);
}
}, [props.columns]);
/**
* 处理列宽调整的回调函数
* @param {number} index - 列的索引
* @returns {Function} - 列宽调整时的实际处理函数
*/
const handleResize = (index) => (_, { size }) => {
const newColumns = [...columns];
newColumns[index] = {
...newColumns[index],
width: size.width,
};
setColumns(newColumns);
};
const mergeColumns = columns.map((col, index) => ({
...col,
onHeaderCell: (column) => ({
// 如果未提供列宽,默认使用 80
width: column.width || 80,
onResize: handleResize(index),
}),
}));
return (
<div className="resizeTable">
<ProTable
{...props}
components={{
header: {
cell: ResizableTitle,
},
}}
scroll={{ x: 900 }}
columns={mergeColumns}
/>
</div>
);
};
export default ResizableTable;
3. 业务组件集成
ini
import ResizableTable from '@/components/ResizableTable';
const BusinessComponent = () => {
// 列配置需包含精确宽度
const columns = [
{ title: '区域机构', dataIndex: 'orgName', width: 200 },
{ title: '传片数', dataIndex: 'uploads', width: 80 },
{ title: 'AI阳性率', dataIndex: 'positiveRate', width: 120 },
];
return (
<div className="data-container">
<ResizableTable
size="small"
rowKey="id"
columns={columns}
dataSource={dataset}
pagination={{ pageSize: 50 }}
/>
</div>
);
};
4. 样式优化方案
css
.resizeTable {
.react-resizable {
position: relative;
background-clip: padding-box;
user-select: none;
}
// 防止默认出现横向滚动条
.ant-table-content > table {
min-width: calc(100% - 5px) !important;
}
.react-resizable-handle {
position: absolute;
width: 10px;
height: 100%;
bottom: 0;
right: -5px;
cursor: col-resize;
background-image: none;
z-index: 1;
}
}
方案优势
- 逻辑解耦:将拖拽逻辑封装为独立高阶组件,实现业务零侵入
- 精准控制:要求列定义必须包含数值型 width 属性,避免渲染抖动
- 样式隔离:通过容器类名限制样式作用域,防止全局污染