文章介绍了如何在AntDesign3.x中利用react-resizable实现列的可伸缩功能,包括安装方法、组件封装和解决松开鼠标仍能拖动的问题。同时提到了使用`use-antd-resizable-header`库的改进方案,使得列伸缩更为便捷和稳定。
摘要由CSDN通过智能技术生成
需求背景:需要实现Antd Table 组件的列伸缩,宽度可以拖拽
在Antd 3.x 的版本中是保留的列伸缩的Demo例子的:
借助
react-resizable
可以实现伸缩列。
npm install react-resizable --save
yarn add react-resizable
参考官方的Demo,封装一个ResizableTable组件:
import { Table } from 'antd';
import type { ColumnsType } from 'antd/lib/table';
import { useEffect,useState } from 'react';
import { Resizable } from 'react-resizable';
import styles from './resizableTable.less';
* 处理松开鼠标还会拖动的问题
* 参考思路:在点击拖动时,使用浏览器API Selection.removeAllRanges 清空原本误选的文本。
const clearSelection = () => {
if (window.getSelection) {
const selection = window.getSelection();
if (selection) {
if (selection.empty) {
selection.empty();
} else if (selection.removeAllRanges) {
selection.removeAllRanges();
else if (document.selection && document.selection.empty) {
document.selection.empty();
export const ResizableTitle = (props: any) => {
const { onResize, width, minWidth, maxWidth, ...restProps } = props;
if (!width) {
return <th {...restProps} />;
const minConstraints: [number, number] | undefined = minWidth
? [minWidth, -Infinity]
: undefined;
const maxConstraints: [number, number] | undefined = maxWidth
? [maxWidth, +Infinity]
: undefined;
return (
<Resizable
width={width}
height={0}
minConstraints={minConstraints}
maxConstraints={maxConstraints}
handle={
className="react-resizable-handle"
onClick={(e) => {
e.stopPropagation();
onResize={onResize}
draggableOpts={{
enableUserSelectHack: false,
onMouseDown: () => {
clearSelection();
<th {...restProps} />
</Resizable>
interface DataType {
name: {
first: string;
last: string;
gender: string;
email: string;
login: {
uuid: string;
const columnsData: ColumnsType<DataType> = [
title: 'Name',
dataIndex: 'name',
sorter: true,
render: (name) => `${name.first} ${name.last}`,
width: '20%',
title: 'Gender',
dataIndex: 'gender',
filters: [
{ text: 'Male', value: 'male' },
{ text: 'Female', value: 'female' },
width: '20%',
title: 'Email',
dataIndex: 'email',
const ResizableTable = () => {
const curColumns: ColumnsType<DataType> = columnsData;
const [column, setColumns] = useState<ColumnsType<any>>([]);
const handleResize = (index: number) => {
return (_e: any, { size }: any) => {
const newCols = [...column];
newCols[index] = {
...newCols[index],
width: size.width || '100%',
setColumns(newCols);
const mergeColumns = column.map((col, index) => ({
...col,
onHeaderCell: (column: any) => ({
width: column.width ?? 100,
minWidth: 50,
onResize: handleResize(index),
}),
}));
useEffect(() => {
console.log('变化', curColumns);
if (curColumns) {
setColumns(curColumns);
}, [curColumns]);
return (
<div className={styles.resizeTable}>
<Table
size="small"
components={{
header: {
cell: ResizableTitle,
columns={mergeColumns}
dataSource={[]}
</div>
export default ResizableTable;
必须引入样式 resizableTable.less
:
.resizeTable {
: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;
.ant-table-filter-column,
.ant-table-column-sorters {
display: flex;
align-items: center;
justify-content: space-around;
min-width: 70px;
.ant-table-thead>tr>th .ant-table-column-sorter {
// margin-top: -21px;
display: table-cell;
vertical-align: middle;
必须保持一列宽度不设置,自适应。否则效果不对。
但我用这个插件后还是不太 OK,总有一些bug,比如如果拖动了不设置宽的列,整个伸缩就会变形;而且如果列数很多的情况下,自适应列效果不理想。
所有这个方案能用但不是很好用。
可以参考:https://juejin.cn/post/7182423243553734717
后续解决方案:
在查阅资料时,看到有个大佬封装好了一个伸缩hook use-antd-resizable-header
,使用起来方便简单。遂引入项目。
https://github.com/hemengke1997/use-antd-resizable-header
pnpm add @minko-fe/use-antd-resizable-header
引入封装组件示例:
import { Table } from 'antd';
import { useAntdResizableHeader } from '@minko-fe/use-antd-resizable-header';
import '@minko-fe/use-antd-resizable-header/dist/style.css';
import { isLocaleEn } from '@/utils/commont_rely';
import type { IProps } from '..';
import './style.less';
interface ResizableTableProps extends IProps {
defaultWidth?: number;
minConstraints?: number;
maxConstraints?: number;
export default function ResizableTable(props: ResizableTableProps) {
const { title, defaultWidth, minConstraints, maxConstraints } = props;
const columns = props?.columns || [];
const { components, resizableColumns, tableWidth } = useAntdResizableHeader({
columns,
defaultWidth: defaultWidth || 120,
minConstraints: minConstraints || 60,
maxConstraints: maxConstraints || 800,
});
return (
<div className="resizableTable">
<Table
title={title}
size="small"
dataSource={data}
columns={resizableColumns}
components={components}
scroll={{ x: tableWidth }}
</div>
使用方便,效果理想,推荐使用这个插件。
11.29 更新
升级到v2.9.0
,不需要引入css文件
注意: 依赖包的名字也变了
pnpm add use-antd-resizable-header
通过 集成
react-resizable 来
实现可
伸缩列。
首先引入Resizable
import { Resizable } from ‘
react-resizable’;
通过替换
table组件本身的components中的header的cell;
将每一个th都用Resizable包裹起来 如下(如下)
//仅代表思路的代码
<Resizable
width={width}
height={0}
on
Resize={on
Resize}
问题描述:
为了向用户展示更丰富的数据,更多的内容,需在展示的列表页中设置列宽可随意拖动。antd官网提供了列宽可拖动的示例,经测试原示例并不好用,且使用有限制,列宽拖拽响应很慢,拖动时会造成其它列宽比较大的变化,针对内容较多的列并不能做到随着列宽的变化,内容也相应增减。
antd现可伸缩列问题展示
1. antd官网示例,当列宽拖动到比内容小时,内容将会出现换行,将行高度撑开
2....
import { FC, useState } from '
react'
import { Resizable } from '
react-resizable'
// 引入
react-resizable npm i xxx 或 yarn add xxx
import { deBounce } from '@/utils/utilConvenrt'
// 防抖
经过一番排查发现
antd3.x是有可伸缩列这一项的demo的
地址是:https://ant.design/components/table-cn/#components-table-demo-resizable-column
当我用该地址切换4.x,4.x出现了可伸缩列这一个demo
而当我去掉url的#components-table-demo-resizable-colum
实现方式
react-resizable GitHub
首先百度寻找解决方案,很容易的,我们就找到了react-resizable,这个解决方案在antd 3.x 的文档中,表格 Table - Ant Design,但是在更高的版本中没有,如果不是百度,我应该永远找不到.
npm install --save react-resizable
官方提供的代码示例:
import { Ta
遇到的问题是官方可伸缩列拖动的时候太卡,究其原因是实时更新列宽,拖动的时候直接更新所有列宽,当列较多的时候更新的数据响应也会比较多,但做法是官方的延申
package.json
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"antd": "^
function exportToExcel(data, fileName) {
const sheetName = 'Sheet1';
const workbook = XLSX.utils.book_new();
const worksheet = XLSX.utils.json_to_sheet(data);
XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
saveAs(
new Blob([excelBuffer], { type: 'application/octet-stream' }),
`${fileName}.xlsx`,
最后,在需要导出 Excel 表格的事件中调用这个函数即可:
```javascript
handleExportExcel = () => {
const data = [
{ name: 'John Doe', age: 35 },
{ name: 'Jane Doe', age: 30 },
exportToExcel(data, 'users');
这个例子中,我们将一个包含两个用户信息的数组作为数据传入,将文件名设置为 `users`,点击按钮后就会弹出下载 Excel 文件的窗口。