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

使用dragEnter/dragLeave实现拖拽交换时元素高亮的问题求助

解决拖拽交换时目标元素高亮问题

核心问题分析

你遇到的dragEnter/dragLeave失效问题,本质是浏览器事件机制导致的:当拖拽元素进入目标元素的子节点时,会触发目标元素的dragLeave事件,意外移除高亮样式。

修复方案

通过计数器跟踪进入次数,配合dragover事件处理,确保只有完全离开目标元素时才取消高亮:

  1. 修改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;
  }
});
  1. 添加高亮样式(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);
}
  1. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:01:09