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

React+Antd Table中onDragEnter/onDragLeave事件多次触发求助

解决Antd Table外层div拖拽事件多次触发问题

问题原因

Antd Table组件内部包含大量嵌套DOM节点(表头、单元格、滚动容器等),当拖拽元素在这些子节点间移动时,浏览器会频繁触发外层div的onDragEnter和onDragLeave事件——每次从父节点进入子节点时,会触发父节点的onDragLeave,再触发子节点的onDragEnter,事件冒泡到外层div后,导致外层的事件处理函数被多次调用,无法正确控制边框的显示状态。

解决方案:精准判断拖拽边界

通过event.currentTarget和event.relatedTarget判断拖拽动作是否真正离开外层容器,只在进入/离开容器本身时更新状态,忽略容器内部子元素间的拖拽移动。

完整代码示例

import { useState } from 'react';
import { Table } from 'antd';

const DragTableContainer = () => {
  const [isDraggingOver, setIsDraggingOver] = useState(false);
  
  // 示例列配置
  const columns = [
    { title: '姓名', dataIndex: 'name', key: 'name' },
    { title: '年龄', dataIndex: 'age', key: 'age' },
    { title: '地址', dataIndex: 'address', key: 'address' },
  ];
  
  // 示例数据
  const data = [
    { key: '1', name: '张三', age: 28, address: '北京' },
    { key: '2', name: '李四', age: 32, address: '上海' },
  ];

  const handleDragEnter = (e) => {
    // 仅当从容器外部进入,或直接进入容器本身时,标记为拖拽中
    if (!e.currentTarget.contains(e.relatedTarget)) {
      setIsDraggingOver(true);
    }
  };

  const handleDragLeave = (e) => {
    // 仅当拖拽元素真正离开容器范围时,取消拖拽状态
    if (!e.currentTarget.contains(e.relatedTarget)) {
      setIsDraggingOver(false);
    }
  };

  const handleDrop = (e) => {
    e.preventDefault();
    setIsDraggingOver(false);
    // 这里添加你的拖拽落地逻辑
    console.log('拖拽完成');
  };

  return (
    <div
      style={{
        padding: '16px',
        border: isDraggingOver ? '2px dashed #1890ff' : '2px solid transparent',
        borderRadius: '4px',
        transition: 'border-color 0.2s ease'
      }}
      onDragEnter={handleDragEnter}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
      onDragOver={(e) => e.preventDefault()} // 必须阻止默认事件,否则无法触发drop
    >
      <Table 
        columns={columns} 
        dataSource={data} 
        bordered 
        pagination={false}
      />
    </div>
  );
};

export default DragTableContainer;

关键说明

  • onDragOver必须阻止默认事件:浏览器默认会阻止拖拽操作,调用e.preventDefault()才能让onDrop事件触发,同时确保拖拽状态判断逻辑正常工作。
  • contains方法的作用:通过e.currentTarget.contains(e.relatedTarget)判断拖拽事件的目标元素是否属于外层容器的子节点,以此区分"在容器内部移动"和"真正离开容器"两种场景,避免不必要的状态更新。

内容的提问来源于stack exchange,提问作者SollierMathieu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 21:38:23