You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
问题排查与修复

核心问题原因

  1. 原生拖拽属性冲突:给拖拽手柄添加了draggable={true},浏览器会触发原生拖拽事件,干扰手动绑定的mouseup事件,导致释放鼠标时无法正常触发handleMouseUp。
  2. 事件监听未清理完全:handleMouseUp中仅移除了mousemove监听,未移除自身的mouseup监听,会导致重复绑定和内存泄漏。
  3. 未阻止默认行为: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 11:33:14