Antd+React+react-resizable实现表格拖拽功能
1、先看效果

2、环境准备
在package.json 引入相关的依赖
"dependencies": {"antd": "^5.4.0","react-resizable": "^3.0.4",},"devDependencies": {"@types/react": "^18.0.33","@types/react-resizable": "^3.0.1",}
3、功能实现
一、拖拽组件实现
1、导入所需组件:在你的代码文件中导入所需的组件:
import { Resizable, ResizableProps } from 'react-resizable';
2、创建可调整大小的列组件:为了实现表格拖拽功能,你需要为每一列创建一个可调整大小的组件。在每个表格列的头部,使用Resizable组件来包裹列的内容:
/*** 公共组件:实现拖拽*/
import { isNumber } from 'lodash';
import { StyleHTMLAttributes } from 'react';
import { Resizable, ResizableProps } from 'react-resizable';type ResizableTitleProps = ResizableProps & {resizable?: boolean;style: StyleHTMLAttributes<any>;
};const ResizableTitle = (props: ResizableTitleProps) => {const { onResize, width, resizable, ...restProps } = props;if (!width || !resizable) {return <th {...restProps} />;}let resizeWidth: any = width;if (!isNumber(resizeWidth)) {resizeWidth = Number(resizeWidth.replace('px', ''));}return (<Resizablewidth={resizeWidth}height={0}handle={<spanclassName="react-resizable-handle"onClick={(e) => {e.stopPropagation();}}/>}onResize={onResize}draggableOpts={{ enableUserSelectHack: true }}// maxConstraints={[800, 800]}><th{...restProps}style={{...restProps?.style,width: `${resizeWidth}px`,borderRight: '1px solid rgba(2, 9, 23, 70%)',}}/></Resizable>);
};export default ResizableTitle;
在上面的代码中,我们使用Resizable组件来包裹了列的内容。handle属性定义了列的调整大小的手柄样式,你可以根据需要自定义。draggableOpts属性用于配置调整大小的选项。
二、在antd写入tab,并引用该拖拽组件
1、在table的components属性中,引入该拖拽组件
<Table...{...(isResizable? {components: {header: {cell: ResizableTitle, // 动态拖拽设置列宽},},}: {})}columns={getColumns(currentColumns)}{...props}/>
2、对每一列的onHeaderCell都加上拖拽的属性resizable,控制该列是否可拖拽,配置onResize的回调方法
const getColumns = (columns: any) => {return (columns || []).map((col: any, idx: number) => {return {...col,onHeaderCell: (column: any) => ({width: column.width || 100,resizable: isResizable && !column?.fixed,onResize: handleResize(idx, col.dataIndex as string),}),};});};
3、拖拽后更新表格的列宽
// 拖拽后更新表格宽度const handleResize =(index: number, colDataIndex?: string) =>(e: any, { size }: { size: { width: number } }) => {if (!colDataIndex) {return;}setCurrentColumns((pre) => {let temp = [...pre];temp[index] = {...temp[index],width: size.width < 50 ? 50 : size.width,};computedWidth(temp);return temp;});};
4、具体实现如下:
import { Table } from 'antd';
import clsx from 'clsx';
import React, { useEffect, useState } from 'react';
import ResizableTitle from './ResizableTitle';
import styles from './index.less';export interface ListTableProps {className?: any;rowClassName?: any;dimension?: number;columns?: any;dataSource?: any;pagination?: any;scroll?: object;virtual?: boolean;rowKey?: any;isShowScrollX?: boolean;vid?: string;isResizable?: boolean; //是否可退拽onChange?: (pagination: any, filters: any, sorter: any) => void;
}// 暂无数据组件
const NoDataComponent = () => {return (<div className={clsx(['h-[250px]', 'flex justify-center items-center'])}><divclassName={clsx(['w-[76px] h-[94px]','bg-[url("/images/no-data.svg")] bg-no-repeat',])}/></div>);
};const ListTable: React.FC<ListTableProps> = ({className,rowClassName = () => '',onChange,dataSource,isShowScrollX,defaultFixedNode,columns: initCols,isResizable,vid = 'resize_table',...props
}) => {const [currentColumns, setCurrentColumns] = useState([]);const [leftRightNodeIsFixed, setLeftRightNodeIsFixe] =useState(defaultFixedNode); // 左右节点是否固定useEffect(() => {setCurrentColumns(initCols);}, [initCols]);useEffect(() => {setCurrentColumns(initCols);}, [initCols]);// 计算宽度,当出现底部滚动条时,最左最右节点固定const computedWidth = (columns: any) => {const widthAll =document.getElementsByClassName('ant-table-body')?.[0]?.clientWidth;const currentTabWidth = (columns || []).reduce((pre: number, cur: any) => {return Number(pre) + (Number(cur?.width) || 0);}, 0);setLeftRightNodeIsFixe(currentTabWidth > widthAll);};
// 拖拽后更新表格宽度const handleResize =(index: number, colDataIndex?: string) =>(e: any, { size }: { size: { width: number } }) => {if (!colDataIndex) {return;}setCurrentColumns((pre) => {let temp = [...pre];temp[index] = {...temp[index],width: size.width < 50 ? 50 : size.width,};computedWidth(temp);return temp;});};const getColumns = (columns: any) => {return (columns || []).map((col: any, idx: number) => {return {...col,onHeaderCell: (column: any) => ({width: column.width || 100,resizable: isResizable && !column?.fixed,onResize: handleResize(idx, col.dataIndex as string),}),};});};return (<TablerowClassName={(record, index) => {return rowClassName(record, index);}}locale={{ emptyText: <NoDataComponent /> }}{...(isResizable? {components: {header: {cell: ResizableTitle, // 动态拖拽设置列宽},},}: {})}columns={getColumns(currentColumns)}onChange={onChange}dataSource={dataSource}{...props}/>);
};export default ListTable;
4、常见问题:
1、拖拽时,鼠标离开,拖拽被还原,80%原因是因为父组件触发了useState更新,column被还原成初始态,
2、拖拽要设置最小宽度和最大宽度,防止拖拽过程中找不到元素
相关文章:
Antd+React+react-resizable实现表格拖拽功能
1、先看效果 2、环境准备 在package.json 引入相关的依赖 "dependencies": {"antd": "^5.4.0","react-resizable": "^3.0.4",},"devDependencies": {"types/react": "^18.0.33","types…...
StringBuilder类常用方法(Java)
StringBuilder类常用方法 StringBuilder 是 Java 中常用的字符串缓冲区类,适用于频繁修改字符串的场景。 1. append(): 将指定字符串、字符、布尔值或其他数据类型的表示追加到字符串缓冲区的末尾。 StringBuilder sb new StringBuilder("Hello"); sb.…...
Iceberg从入门到精通系列之二十一:Spark集成Iceberg
Iceberg从入门到精通系列之二十一:Spark集成Iceberg 一、在 Spark 3 中使用 Iceberg二、添加目录三、创建表四、写五、读六、Catalogs七、目录配置八、使用目录九、替换会话目录十、使用目录特定的 Hadoop 配置值十一、加载自定义目录十二、SQL 扩展十三、运行时配置…...
Linux的进程信号
注意:首先需要提醒一个事情,本节提及的进程信号和下节的信号量没有任何关系,请您区分对待。 1.信号概念 1.1.生活中的信号 我们在生活中通过体验现实,记忆了一些信号和对应的处理动作,这意味着信号有以下相关的特点&…...
svn常用命令及过滤文件 global ignore pattern
SVN常用命令详解和global ignore pattern Subversion(SVN)是一个版本控制系统,广泛用于软件开发项目中。它能够追踪文件的变更,并且允许多人在同一个项目中协同工作。以下是一些常用的SVN命令及其用法。 1. 检出代码 要从SVN服…...
【QT+QGIS跨平台编译】之二十九:【HDF5+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
文章目录 一、HDF5介绍二、文件下载三、文件分析四、pro文件一、HDF5介绍 HDF5(层次数据格式第5版)是一种用于存储和组织大量数据的文件格式和技术集合。它由美国国家超级计算应用中心(NCSA)开发,旨在解决复杂数据的存储和分布问题。HDF5支持各种数据类型,能够有效地存储…...
React 中实现拖拽功能-插件 react-beautiful-dnd
拖拽功能在平时开发中是很常见的,这篇文章主要使用react-beautiful-dnd插件实现此功能。 非常好用,附上GitHub地址:https://github.com/atlassian/react-beautiful-dnd 安装及引入 // 1.引入 # yarn yarn add react-beautiful-dnd# npm npm…...
golang 引入swagger(iris、gin)
golang 引入swagger(iris、gin) 在开发过程中,我们不免需要调试我们的接口,但是有些接口测试工具无法根据我们的接口变化而动态变化。文档和代码是分离的。总是出现文档和代码不同步的情况。这个时候就可以在我们项目中引入swagge…...
Java开发IntelliJ IDEA2023
IntelliJ IDEA 2023是一款强大的集成开发环境(IDE),专为Java开发人员设计。它提供了许多特色功能,帮助开发人员更高效地编写、测试和调试Java应用程序。以下是一些IntelliJ IDEA 2023的特色功能: 智能代码编辑器&…...
LeetCode LCP 30.魔塔游戏:贪心(优先队列)
【LetMeFly】LCP 30.魔塔游戏:贪心(优先队列) 力扣题目链接:https://leetcode.cn/problems/p0NxJO/ 小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1。每个房间的补血道具/怪物对于血量影响记于…...
Oracle的权限
通过用户登录plsql工具后,如果在创建视图(或其他对象)时,没有指明视图或对象的用户,该视图或对象将直接创建在当前登录用户下。 GRANT SELECT ON user2.table1 TO user1;//将用户2的表1的select权限给用户1 GRANT ALL ON user2.table1 TO u…...
20240206三次握手四次挥手
TCP和UDP异同点 相同点:同属于传输层的协议 不同点: TCP ----> 稳定 1> 提供面向连接的,可靠的数据传输服务 2> 传输过程中,数据无误、数据无丢失、数据无失序、数据无重复 1、TCP会给每个数据包编上编号ÿ…...
Navicat的使用教程,操作详解
这篇文章主要针对mysql数据库。 在使用Navicat之前,首先要确保你在本地已经安装好了,mysql数据库,安装教程可以参考我的另一篇博文 在windows平台上mysql的安装教程-CSDN博客 1.Navicat连接你的数据库 连接名,随便写,…...
Git―基本操作
Git ⛅认识 Git⛅安装 GitCentos(7.6)Ubuntu ⛅Git―基本操作创建本地仓库🍂配置本地仓库🍂工作区, 暂存区, 版本库🍂版本库工作区 添加文件🍂查看文件🍂修改文件🍂版本回退🍂☃️案例 撤销修改…...
【PostgreSQL内核学习(二十六) —— (共享数据缓冲区)】
共享数据缓冲区 概述共享数据缓冲区管理共享缓冲区管理的核心功能包括: 共享数据缓冲区的组织结构初始化共享缓冲池BufferDesc 结构体InitBufferPool 函数 如何确定请求的数据页面是否在缓冲区中?BufferTag 结构体RelFileNode 结构体ForkNumber 结构体Re…...
word调整论文格式的记录
页眉的分章显示内容 效果: 步骤: 确保“显示/隐藏的标记”符号打开点亮 前提是章节前面有“分节符(下一页)”,没有则添加,在菜单栏“布局”——》“下一页” 添加页眉,双击页眉,选…...
android.MediaMuxer时间裁剪
使用MediaMuxer裁剪视频_安卓muxer 裁剪视频画布-CSDN博客 关键步骤 mediaExtractor.seekTo(beginTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);long presentTimeUs mediaExtractor.getSampleTime(); if (presentTimeUs > endTime)break; 功能代码 VideoView videoVie…...
【蓝桥杯选拔赛真题91】Scratch筛选数据 第十五届蓝桥杯scratch图形化编程 少儿编程创意编程选拔赛真题解析
目录 scratch筛选数据 一、题目要求 编程实现 二、案例分析 1、角色分析...
英语学习——16组英语常用短语
第1组:look look at 看 look for 寻找 look up 查阅,向上看 look out 向外看,小心 look after 照顾 look like 看起来像 look through 浏览 look into 向里看 look around 环顾四周 look forward to 期盼 look ahead 向前看 Look…...
unity 增加系统时间显示、FPS帧率、ms延迟
代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;using UnityEngine;public class Frame : MonoBehaviour {// 记录帧数private int _frame;// 上一次计算帧率的时间private float _lastTime;// 平…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
