什么是事件冒泡和捕获?
事件冒泡和捕获有什么区别? 在这两个,这是更快,更好的模式使用?
事件冒泡和捕获是事件在HTML DOM API中传播的两种方式,当一个事件发生在另一个元素内部的一个元素中时,这两个元素都注册了该事件的句柄。 事件传播模式确定元素以哪种顺序接收事件 。
冒泡时,事件首先被最内层元素捕获并处理,然后传播到外层元素。
捕获时,事件首先被最外层的元素捕获并传播到内层元素。
捕获也被称为“滴漏”,这有助于记住传播顺序:
滴下来,起泡
在过去,网景主张事件捕捉,而微软则推动事件冒泡。 两者都是W3C 文档对象模型事件标准(2000)的一部分。
IE <9 只使用事件冒泡 ,而IE9 +和所有主stream浏览器都支持。 另一方面,对于复杂的DOM ,事件冒泡的性能可能会略微降低 。
我们可以使用addEventListener(type, listener, useCapture)
以冒泡(默认)或捕获模式注册事件处理程序。 要使用捕捉模型,请将第三个参数作为true
。
例
<div> <ul> <li></li> </ul> </div>
在上面的结构中,假设li
元素中发生了点击事件。
在捕获模型中,事件将首先由div
处理(在div
单击事件处理程序将首先触发),然后在ul
,然后在目标元素li
最后处理。
在冒泡模式中,会发生相反的情况:事件将首先由li
,然后由ul
,最后由div
元素处理。
有关更多信息,请参阅
- QuirksMode上的事件顺序
- MDN上的addEventListener
- QuirksMode上的高级事件
在下面的示例中,如果单击任何突出显示的元素,则可以看到事件传播stream的捕获阶段首先出现,然后是冒泡阶段。
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()); } 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); }
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> <section id="log"></section>
描述:
quirksmode.org对此有一个很好的描述。 简而言之(从quirksmode复制):
事件捕获
当你使用事件捕获
| | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | -----------------------------------
element1的事件处理程序首先触发,element2的事件处理程序最后触发。
事件冒泡
当你使用事件冒泡
/ \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | -----------------------------------
element2的事件处理程序首先触发,element1的事件处理程序最后触发。
使用什么?
这取决于你想要做什么。 没有更好的。 区别在于事件处理程序的执行顺序。 大多数情况下,在冒泡阶段触发事件处理程序是可以的,但也可能有必要提前触发它们。
如果有两个元素元素1和元素2.元素2是在元素1内,我们附加一个事件处理程序,两个元素让我们说onClick。 现在当我们点击元素2时,两个元素的eventHandler将被执行。 现在问题在于事件的执行顺序。 如果元素1附加的事件首先执行,则称为事件捕获,如果元素2附加的事件首先执行,则称为事件冒泡。 根据W3C,事件将在捕获阶段开始,直到它到达目标回到元素,然后开始冒泡
捕获和冒泡状态由addEventListener方法的useCapture参数所知
eventTarget.addEventListener(types,听众,[方法,useCapture]);
默认情况下,useCapture为false。 这意味着它正处于冒泡阶段。
var div1 = document.querySelector("#div1"); var div2 = document.querySelector("#div2"); div1.addEventListener("click", function (event) { alert("you clicked on div 1"); }, true); div2.addEventListener("click", function (event) { alert("you clicked on div 2"); }, false);
#div1{ background-color:red; padding: 24px; } #div2{ background-color:green; }
<div id="div1"> div 1 <div id="div2"> div 2 </div> </div>
我已经在javascript.info上find了这个教程,在解释这个主题的时候非常清楚。 最后的3分总结真的是在谈论关键点。 我在这里引用它:
- 事件首先被捕获到最深的目标,然后冒泡。 在IE浏览器<9他们只泡。
- 所有的处理器都在冒泡阶段工作,除了addEventListener的最后一个参数是true之外,这是在捕获阶段捕获事件的唯一方法。
- 冒泡/捕获可以通过event.cancelBubble = true(IE)或event.stopPropagation()为其他浏览器停止。