事件冒泡和捕获之间的区别是什么?什么时候应该使用冒泡和捕获?


当前回答

DOM Events描述了事件传播的3个阶段:捕获阶段——事件向下到元素。目标阶段——事件到达目标元素。冒泡阶段——事件从元素冒泡。

其他回答

我发现这个教程在javascript.info中非常清楚地解释了这个主题。它最后的3点总结是对关键点的讨论。我在这里引用:

事件首先被捕捉到最深的目标,然后向上冒泡。在 IE<9,它们只是冒泡。 所有处理程序都在冒泡阶段上工作,除了 addEventListener的最后一个参数为真,这是唯一的方法 在捕获阶段捕获事件。 冒泡/捕获可以 由事件停止。cancelBubble=true (IE)或event.stopPropagation() 对于其他浏览器。

DOM Events描述了事件传播的3个阶段:捕获阶段——事件向下到元素。目标阶段——事件到达目标元素。冒泡阶段——事件从元素冒泡。

描述:

quirksmode。org对此有一个很好的描述。简而言之(摘自quirksmode):

Event capturing When you use event capturing | | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | ----------------------------------- the event handler of element1 fires first, the event handler of element2 fires last. Event bubbling When you use event bubbling / \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | ----------------------------------- the event handler of element2 fires first, the event handler of element1 fires last.


用什么?

这取决于你想做什么。没有更好的了。不同之处在于事件处理程序的执行顺序。大多数情况下,在冒泡阶段触发事件处理程序是可以的,但也有必要在更早的时候触发它们。

事件冒泡和捕获是HTML DOM API中事件传播的两种方式,当一个事件发生在另一个元素中的元素中,并且两个元素都为该事件注册了句柄。事件传播模式决定元素接收事件的顺序。

使用冒泡,事件首先由最内部的元素捕获和处理,然后传播到外部元素。

通过捕获,事件首先由最外层的元素捕获并传播到内部元素。

捕捉也被称为“涓滴”,这有助于记住传播顺序:

涓滴而下,泡沫而起

在过去,Netscape提倡事件捕获,而微软则提倡事件冒泡。两者都是W3C文档对象模型事件标准(2000)的一部分。

IE < 9只使用事件冒泡,而IE9+和所有主流浏览器都支持这两种方式。另一方面,对于复杂的dom,事件冒泡的性能可能略低。

我们可以使用addEventListener(type, listener, useCapture)以冒泡(默认)或捕获模式注册事件处理程序。要使用捕获模型,将第三个参数传递为true。

例子

<div>
    <ul>
        <li></li>
    </ul>
</div>

在上面的结构中,假设li元素中发生了单击事件。

在捕获模型中,事件将首先由div处理(在div中单击事件处理程序将首先触发),然后是ul,最后是目标元素li。

在冒泡模型中,将发生相反的情况:事件将首先由li处理,然后由ul处理,最后由div元素处理。

有关更多信息,请参见

QuirksMode上的事件顺序 addEventListener在MDN QuirksMode上的高级事件

在下面的示例中,如果单击任何突出显示的元素,可以看到事件传播流的捕获阶段首先发生,然后是冒泡阶段。

var logElement = document.getElementById('log'); function log(msg) { logElement.innerHTML += ('<p>' + msg + '</p>'); } function capture() { log('capture: ' + this.firstChild.nodeValue.trim()); } function bubble() { log('bubble: ' + this.firstChild.nodeValue.trim()); } function clearOutput() { logElement.innerHTML = ""; } var divs = document.getElementsByTagName('div'); for (var i = 0; i < divs.length; i++) { divs[i].addEventListener('click', capture, true); divs[i].addEventListener('click', bubble, false); } var clearButton = document.getElementById('clear'); clearButton.addEventListener('click', clearOutput); p { line-height: 0; } div { display:inline-block; padding: 5px; background: #fff; border: 1px solid #aaa; cursor: pointer; } div:hover { border: 1px solid #faa; background: #fdd; } <div>1 <div>2 <div>3 <div>4 <div>5</div> </div> </div> </div> </div> <button id="clear">clear output</button> <section id="log"></section>

JSFiddle的另一个例子。

冒泡

  Event propagate to the upto root element is **BUBBLING**.

捕捉

  Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.