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
相关产品推荐
相关产品推荐

