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

