Javascript OnDrop事件目标在子级上丢弃时为子级,即使使用了捕获阶段

Javascript OnDrop事件目标在子级上丢弃时为子级,即使使用了捕获阶段,javascript,html,drag-and-drop,dom-events,event-capturing,Javascript,Html,Drag And Drop,Dom Events,Event Capturing,我试图使我的拖放操作在JavaScript中正常工作,而不必显式地扫描父元素或其他ID、类循环和其他黑客魔法 现在,当我拖动元素池中的一个元素并将其拖动到灰色区域时,该元素将复制到拖放区域(到目前为止,一切都是正确的)。我基本上是复制被拖动元素的HTML,清除拖放区域(目标),然后向其中添加新元素 当您在放置区域中已经有一些子元素并且您将其拖动到子元素上时,问题就开始了。然后drop事件中的目标是子元素,而不是事件所附加到的div。这将导致被拖动的元素被清除,并将其自身复制到子元素中,而不是放置

我试图使我的拖放操作在JavaScript中正常工作,而不必显式地扫描父元素或其他ID、类循环和其他黑客魔法

现在,当我拖动元素池中的一个元素并将其拖动到灰色区域时,该元素将复制到拖放区域(到目前为止,一切都是正确的)。我基本上是复制被拖动元素的HTML,清除拖放区域(目标),然后向其中添加新元素

当您在放置区域中已经有一些子元素并且您将其拖动到子元素上时,问题就开始了。然后drop事件中的目标是子元素,而不是事件所附加到的div。这将导致被拖动的元素被清除,并将其自身复制到子元素中,而不是放置容器中

预期的结果应该是,无论您将其放置在子节点上还是直接放置在主放置容器上,目标都应该始终是父节点,因为我使用的是事件捕获模式

下面是我在JS Fiddle中的示例代码。我将事件侦听器与捕获一起使用,但它似乎正在进行冒泡阶段,而忽略了捕获阶段。为什么?

正确的方法是什么

onDrag功能(ev){
var el=电动汽车目标;
//log(“拖动:”+ev.target.outerHTML)
setData('text/html',ev.target.outerHTML);
}
功能onContainerOver(ev){
ev.preventDefault();
ev.dataTransfer.dropEffect=“移动”
}
功能onContainerDrop(ev){
ev.preventDefault();
//log(“Drop:”+ev.dataTransfer.getData(“text/html”))
ev.target.innerHTML=ev.dataTransfer.getData(“text/html”);
}
document.getElementById('target')。addEventListener('drop',onContainerDrop,true);//这不应该是泡沫,但它确实存在。目标始终是第一个子元素,而不是事件侦听器所在的元素。为什么???
#列表{}
艾尔先生{
填充物:5px;
利润率:10px;
边框:实心1px黑色;
背景色:#86d4ff;
光标:移动;
线高:1米;
文本对齐:左对齐;
}
#目标{
最小高度:200px;
宽度:100%;
背景色:#ffdea6;
边框:1px灰色虚线;
文本对齐:居中;
线高:100px;
}

元素A
元素B
元素C
到这里来

没关系,我没有注意到事件中“currentTarget”元素的可用性,它正是我想要的

因此,与其使用“event.target”,不如使用“event.currentTarget”来获取触发事件的实际父元素

下面是一个正在工作的JSFIDLE:

更新JS:

function onDrag(ev){
  var el = ev.srcElement;
  console.log("Drag: " + ev.srcElement.outerHTML)
  ev.dataTransfer.setData('text/html', ev.srcElement.outerHTML);
}

function onContainerOver(ev){
  ev.preventDefault();
  ev.dataTransfer.dropEffect = "move"
}

function onContainerDrop(ev){
  ev.preventDefault();
  console.log("Drop: " + ev.dataTransfer.getData("text/html"))
  ev.currentTarget.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???

当您在子元素上放置任何内容或在子元素上发生任何事件时,事件目标始终是子元素,因为它是事件发生的地方。这就是目标

┌─────────────────────────────────────┐
│   ┌────────────────────────┐        │
│   │     Child [Target]     │        │
│   └────────────────────────┘        │
│             Parent                  │
└─────────────────────────────────────┘
然后该事件作为子元素作为TargetCurrentTarget传递给子元素的事件处理程序

┌─────────────────────────────────────┐
│   ┌───────────────────────────────┐ │
│   │ Child [Target][CurrentTarget] │ │
│   └───────────────────────────────┘ │
│         Parent Element              │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│   ┌───────────────────────────────┐ │
│   │        Child [Target]         │ │
│   └───────────────────────────────┘ │
│         Parent [CurrentTarget]      │
└─────────────────────────────────────┘
然后该事件作为子元素作为Target传递给父元素的事件处理程序,作为父元素作为CurrentTarget

┌─────────────────────────────────────┐
│   ┌───────────────────────────────┐ │
│   │ Child [Target][CurrentTarget] │ │
│   └───────────────────────────────┘ │
│         Parent Element              │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│   ┌───────────────────────────────┐ │
│   │        Child [Target]         │ │
│   └───────────────────────────────┘ │
│         Parent [CurrentTarget]      │
└─────────────────────────────────────┘
然后,事件以相同的方式依次传递给dom树中较高的元素,直到到达顶层元素,或者任何事件处理程序通过调用event.stopPropagation()来取消此事件冒泡

那么,当创建将第三个参数useCapture作为true传递的事件处理程序时会发生什么呢

在这种情况下,事件首先传递给父元素[currentTarget:parent],然后传递给子元素[currentTarget:child],但与往常一样,事件目标始终是子元素,因为这是触发事件的地方

关于当前目标

在事件遍历时标识事件的当前目标 大教堂。它始终引用事件处理程序所指向的元素 已附加,而不是标识 发生事件的元素


很好,我也通过在“drop”事件上捕获事件来获取父目标id。。最后,此操作不需要事件捕获。:)