我试图使我的拖放在JavaScript中正常工作,而不必显式扫描父元素或其他ID,类循环和其他骇客魔术。
现在,当我拖动元素池中的元素之一并将其拖动到灰色区域时,该元素会被复制到放置区域(到目前为止一切正常)。我基本上复制拖动元素的 HTML,清除放置区(目标)并将新元素添加到其中。
当您在放置区中已经有一些子元素并将其拖到子元素上时,问题就开始了。然后 drop 事件中的目标是子元素,而不是事件附加到的 div。这将导致拖动的元素被清除,并将其自身复制到子级中,而不是复制到放置容器中。
预期的结果应该是,无论您是将它放在子节点上还是直接放在主放置容器上,目标都应该始终是父节点,因为我使用的是事件捕获模式。
这是我在 JS Fiddle 中的示例代码。我正在使用带有捕获的事件监听器,但它似乎无论如何都在进行冒泡阶段而忽略了捕获阶段。为什么?
这样做的正确方法是什么?
function onDrag(ev) {
var el = ev.target;
//console.log("Drag: " + ev.target.outerHTML)
ev.dataTransfer.setData('text/html', ev.target.outerHTML);
}
function onContainerOver(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move"
}
function onContainerDrop(ev) {
ev.preventDefault();
//console.log("Drop: " + ev.dataTransfer.getData("text/html"))
ev.target.innerHTML = ev.dataTransfer.getData("text/html");
}
document.getElementById('target').addEventListener('drop', onContainerDrop, true); // This should not bubble, but it does. Target is always the child first rather than the element where the event listener resides. Why???
#list {}
.el {
padding: 5px;
margin: 10px;
border: solid 1px black;
background-color: #86d4ff;
cursor: move;
line-height: 1em;
text-align: left;
}
#target {
min-height: 200px;
width: 100%;
background-color: #ffdea6;
border: 1px dashed gray;
text-align: center;
line-height: 100px;
}
<div id="list">
<div class="el" draggable="true" ondragstart="onDrag(event)">ELEMENT A</div>
<div class="el" draggable="true" ondragstart="onDrag(event)">ELEMENT B</div>
<div class="el" draggable="true" ondragstart="onDrag(event)">ELEMENT C</div>
</div>
<div id="target" ondragover="onContainerOver(event)">
Drop Here
</div>
原始的 JSFiddle Link.
最佳答案
当您在子元素上放置任何内容或在子元素上发生任何事件时, 事件目标 始终是子元素,因为那是发生事件的地方。那就是目标。
┌─────────────────────────────────────┐
│ ┌────────────────────────┐ │
│ │ Child [Target] │ │
│ └────────────────────────┘ │
│ Parent │
└─────────────────────────────────────┘
然后将此事件作为 Target 和 CurrentTarget 作为子元素传递给子元素的事件处理程序
┌─────────────────────────────────────┐
│ ┌───────────────────────────────┐ │
│ │ Child [Target][CurrentTarget] │ │
│ └───────────────────────────────┘ │
│ Parent Element │
└─────────────────────────────────────┘
然后这个事件被传递给父元素的事件处理程序作为子元素作为 目标 和父元素作为 CurrentTarget
┌─────────────────────────────────────┐
│ ┌───────────────────────────────┐ │
│ │ Child [Target] │ │
│ └───────────────────────────────┘ │
│ Parent [CurrentTarget] │
└─────────────────────────────────────┘
然后事件以相同的方式依次传递给 dom 树中更高的元素,直到到达顶级元素或任何事件处理程序通过调用 event.stopPropagation() 取消此 事件冒泡
那么当您创建将第三个参数 useCapture 设为 true 的事件处理程序时会发生什么。
parentElement.addEventListener('click', myClickHandler, true);
在这种情况下,事件首先传递给父元素 [currentTarget:Parent],然后传递给子元素 [currentTarget:Child],但与往常一样, 事件目标 始终是 子元素 因为这是事件被触发。
关于 CurrentTarget this MDN WebDocs page 说,
关于javascript - OnDrop 事件目标在放置在子级上时是子级,即使使用捕获阶段,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47811676/