React实现Antd表格列拖拽调整宽度遇handleMouseUp触发异常求助
问题
使用React结合Antd库实现表格列宽调整功能,封装了ResizeableHeaderComponent组件后,拖拽功能可正常运行,但handleMouseUp方法仅在再次点击时触发,释放鼠标时无法触发。相关代码如下:
import React from 'react'; import { memo } from 'react'; const ResizeableHeaderComponent = (props: any) => { const onResize = (event: MouseEvent) => { if (event.movementX != 0) { event.preventDefault(); props.onResize(event, props.index); } }; const handleMouseUp = () => { window.removeEventListener('mousemove', onResize); }; const handleMouseDown = () => { window.addEventListener('mousemove', onResize); window.addEventListener('mouseup', handleMouseUp); }; return ( <> {props.title} <div draggable={true} style={{ position: 'absolute', bottom: 0, right: '-5px', width: '10px', height: '100%', zIndex: 5, cursor: 'col-resize' }} onMouseDown={handleMouseDown} /> </> ); }; export default memo(ResizeableHeaderComponent);
问题排查与修复
核心问题原因
- 原生拖拽属性冲突:给拖拽手柄添加了
draggable={true},浏览器会触发原生拖拽事件,干扰手动绑定的mouseup事件,导致释放鼠标时无法正常触发handleMouseUp。 - 事件监听未清理完全:
handleMouseUp中仅移除了mousemove监听,未移除自身的mouseup监听,会导致重复绑定和内存泄漏。 - 未阻止默认行为:
mousedown时未阻止浏览器默认行为,进一步加剧了原生事件与自定义事件的冲突。
修复后的代码
import React, { useCallback } from 'react'; import { memo } from 'react'; const ResizeableHeaderComponent = (props: any) => { // 使用useCallback缓存函数,配合memo优化性能 const onResize = useCallback((event: MouseEvent) => { if (event.movementX !== 0) { event.preventDefault(); props.onResize(event, props.index); } }, [props.onResize, props.index]); const handleMouseUp = useCallback(() => { window.removeEventListener('mousemove', onResize); // 同时移除mouseup监听,避免重复绑定 window.removeEventListener('mouseup', handleMouseUp); }, [onResize]); const handleMouseDown = useCallback((event: React.MouseEvent) => { // 阻止浏览器默认行为,避免原生拖拽干扰 event.preventDefault(); window.addEventListener('mousemove', onResize); window.addEventListener('mouseup', handleMouseUp); }, [onResize, handleMouseUp]); return ( <> {props.title} <div // 移除原生draggable属性 style={{ position: 'absolute', bottom: 0, right: '-5px', width: '10px', height: '100%', zIndex: 5, cursor: 'col-resize' }} onMouseDown={handleMouseDown} /> </> ); }; export default memo(ResizeableHeaderComponent);
关键修改点
- 移除了拖拽手柄的
draggable={true}属性,避免原生拖拽事件干扰。 - 在
handleMouseDown中添加event.preventDefault(),阻止浏览器默认行为。 - 在
handleMouseUp中补充移除mouseup自身的监听,防止内存泄漏和重复绑定。 - 使用
useCallback缓存事件处理函数,配合memo组件优化渲染性能,避免每次渲染创建新函数导致的不必要重渲染。
内容的提问来源于stack exchange,提问作者anup r
相关产品推荐
相关产品推荐

