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

dragstart事件未正确选中元素 技术求助与问题排查

问题描述

从侧边栏拖拽元素到右侧容器的功能完全正常,但尝试在右侧容器之间拖拽元素时,dragstart事件完全无法触发,只有dragover事件能响应。怀疑是forEach循环的问题,尝试将新克隆的元素推入draggables数组后依旧无效。

问题根源

初始化时你只给侧边栏里的初始元素绑定了dragstart和dragend事件,后续克隆并添加到右侧容器的新元素,哪怕被推入了draggables数组,也没有绑定事件——因为forEach只会在初始化时遍历一次数组,后续新增的元素不会自动获得事件监听。

修复方案

改用事件委托,把事件绑定到上层容器上,这样不管是初始元素还是后续动态添加的元素,触发事件时都会通过事件冒泡被捕获处理;同时调整拖拽元素的获取逻辑,确保容器内的元素能正确触发拖拽。

修改后的完整代码

JavaScript

const droppables = document.querySelectorAll(".web-prev>div");
let draggedItem;

// 事件委托:捕获所有.left-item的拖拽起始事件
document.addEventListener("dragstart", (e) => {
  const target = e.target;
  if (target.classList.contains("left-item")) {
    if (target.parentElement.classList.contains("left-side")) {
      draggedItem = target.cloneNode(true);
    } else {
      draggedItem = target;
    }
    draggedItem.classList.add("is-dragging");
  }
});

document.addEventListener("dragend", () => {
  if (draggedItem) {
    draggedItem.classList.remove("is-dragging");
  }
});

droppables.forEach((zone) => {
  zone.addEventListener("dragover", (e) => {
    e.preventDefault();
    const bottomItem = insertAboveItem(zone, e.clientY);

    if (!bottomItem) {
      zone.appendChild(draggedItem);
    } else {
      zone.insertBefore(draggedItem, bottomItem);
    }
  });
});

const insertAboveItem = (zone, mouseY) => {
  const nonDragging = zone.querySelectorAll(".left-item:not(.is-dragging)");

  let closestItem = null;
  let closestOffset = Number.NEGATIVE_INFINITY;

  nonDragging.forEach((item) => {
    const { top } = item.getBoundingClientRect();
    const offset = mouseY - top;

    if (offset < 0 && offset > closestOffset) {
      closestOffset = offset;
      closestItem = item;
    }
  });

  return closestItem;
};

CSS

* {
  margin:0;
  padding:0;
  box-sizing:border-box;
}

.left-side {
  position:absolute;
  left:0px;
  width:150px;
  border-right:2px solid black;
  height:100vh;
  display:flex;
  align-items:center;
  flex-direction:column;
  gap:7px;
  padding:7px;
}

.left-item {
  width:100%;
  height:100px;
  background:lightgrey;
  border-radius:5px;
  display:flex;
  justify-content:center;
  align-items:center;
}

.web-prev {
  position:absolute;
  left:150px;
  width:calc(100% - 150px);
  height:100%;
  display:flex;
  align-items:center;
  flex-direction:column;
  padding:7px;
  gap:7px;
}

.web-prev>div {
  width:100%;
  min-height:min(20%, 150px);
  background:lightcoral;
  padding:0 7px;
}

.web-prev>div * {
  margin:7px 0;
}

.left-item.is-dragging {
  opacity:.7;
}

HTML

<div class="left-side">
  <div class="left-item a" draggable="true">a</div>
  <div class="left-item b" draggable="true">b</div>
  <div class="left-item c" draggable="true">c</div>
  <div class="left-item d" draggable="true">d</div>
  <div class="left-item e" draggable="true">e</div>
</div>
<div class="web-prev">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:02:04