使用dragEnter/dragLeave实现拖拽交换时元素高亮的问题求助
解决拖拽交换时目标元素高亮问题
核心问题分析
你遇到的dragEnter/dragLeave失效问题,本质是浏览器事件机制导致的:当拖拽元素进入目标元素的子节点时,会触发目标元素的dragLeave事件,意外移除高亮样式。
修复方案
通过计数器跟踪进入次数,配合dragover事件处理,确保只有完全离开目标元素时才取消高亮:
- 修改JavaScript逻辑(dnd.js)
let draggingElement = null; let enterCount = 0; // 跟踪进入目标元素的次数 // 初始化拖拽元素 document.querySelectorAll('[data-draggable="true"]').forEach(el => { el.setAttribute('draggable', true); el.addEventListener('dragstart', (e) => { draggingElement = e.target; e.dataTransfer.effectAllowed = 'move'; }); el.addEventListener('dragend', () => { draggingElement = null; // 重置计数器,避免残留状态 enterCount = 0; // 移除所有高亮 document.querySelectorAll('.highlight').forEach(el => el.classList.remove('highlight')); }); }); // 处理dragenter事件 document.addEventListener('dragenter', (e) => { const target = e.target.closest('[data-draggable="true"]'); if (target && target !== draggingElement) { enterCount++; // 只有第一次进入时添加高亮 if (enterCount === 1) { target.classList.add('highlight'); } } }); // 处理dragleave事件 document.addEventListener('dragleave', (e) => { const target = e.target.closest('[data-draggable="true"]'); if (target && target !== draggingElement) { enterCount--; // 完全离开时移除高亮 if (enterCount === 0) { target.classList.remove('highlight'); } } }); // 必须阻止dragover默认行为,才能触发drop document.addEventListener('dragover', (e) => { e.preventDefault(); }); // 处理drop交换逻辑 document.addEventListener('drop', (e) => { e.preventDefault(); const target = e.target.closest('[data-draggable="true"]'); if (target && target !== draggingElement) { // 执行元素交换逻辑(示例) const parent = target.parentNode; const draggingIndex = Array.from(parent.children).indexOf(draggingElement); const targetIndex = Array.from(parent.children).indexOf(target); if (draggingIndex < targetIndex) { parent.insertBefore(draggingElement, target.nextSibling); } else { parent.insertBefore(draggingElement, target); } // 清理高亮和计数器 target.classList.remove('highlight'); enterCount = 0; } });
- 添加高亮样式(styles.css)
[data-draggable="true"] { padding: 1rem; margin: 0.5rem 0; border: 1px solid #ddd; border-radius: 4px; cursor: move; transition: all 0.2s; } .highlight { border-color: #2196F3; background-color: rgba(33, 150, 243, 0.1); box-shadow: 0 0 0 2px rgba(33, 150, 243, 0.2); }
- HTML元素标记(index.html)
给所有可拖拽元素添加data-draggable="true"属性:
<div data-draggable="true">元素A</div> <div data-draggable="true">元素B</div> <div data-draggable="true">元素C</div> <div data-draggable="true">元素D</div>
关键说明
- 计数器
enterCount:解决子节点触发dragLeave导致的高亮误移除问题,只有当完全离开目标元素(计数归0)时才取消高亮。 dragover事件:必须阻止默认行为,否则浏览器会认为当前元素不可放置,drop事件无法触发,同时也能让拖拽状态正常显示。dragend事件:重置计数器和移除所有高亮,避免拖拽结束后残留异常状态。
内容的提问来源于stack exchange,提问作者Kesavan Subramaniam Che
相关产品推荐
相关产品推荐

