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


当前回答

If there are two elements element 1 and element 2. Element 2 is inside element 1 and we attach an event handler with both the elements lets say onClick. Now when we click on element 2 then eventHandler for both the elements will be executed. Now here the question is in which order the event will execute. If the event attached with element 1 executes first it is called event capturing and if the event attached with element 2 executes first this is called event bubbling. As per W3C the event will start in the capturing phase until it reaches the target comes back to the element and then it starts bubbling

捕获和冒泡状态是通过addEventListener方法的useCapture参数知道的

eventTarget.addEventListener(类型、侦听器(useCapture]);

默认情况下useCapture为false。这意味着它处于冒泡阶段。

var div1 = document.querySelector("#div1"); var div2 = document.querySelector("#div2"); div1。addEventListener(“点击”,函数(事件){ 警报(“您点击了div 1”); },真正的); div2。addEventListener(“点击”,函数(事件){ 警报(“您点击了div 2”); },假); # div1 { 背景颜色:红色; 填充:24 px; } # div2 { 背景颜色:绿色; } < div id = " div1 " > div 1 < div id = " div2 " > div 2 < / div > < / div >

请试着改变真假。

其他回答

描述:

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.


用什么?

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

还有一个事件。eventPhase属性,它可以告诉你事件是在目标还是来自其他地方,浏览器完全支持。

从已接受的答案扩展已经很好的代码片段,这是使用eventPhase属性的输出

var logElement = document.getElementById('log'); function log(msg) { if (logElement.innerHTML == "<p>No logs</p>") logElement.innerHTML = ""; logElement.innerHTML += ('<p>' + msg + '</p>'); } function humanizeEvent(eventPhase){ switch(eventPhase){ case 1: //Event.CAPTURING_PHASE return "Event is being propagated through the target's ancestor objects"; case 2: //Event.AT_TARGET return "The event has arrived at the event's target"; case 3: //Event.BUBBLING_PHASE return "The event is propagating back up through the target's ancestors in reverse order"; } } function capture(e) { log('capture: ' + this.firstChild.nodeValue.trim() + "; " + humanizeEvent(e.eventPhase)); } function bubble(e) { log('bubble: ' + this.firstChild.nodeValue.trim() + "; " + humanizeEvent(e.eventPhase)); } 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> <button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button> <section id="log"></section>

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

冒泡

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

捕捉

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

当浏览器检测到事件时,它会尝试查找事件处理程序。这个过程有三个阶段。假设我们有这些元素

   <body>
      <div>
        <button>click</button>
      </div>
    </body>

1-Capture阶段

browser is going to take a look at the element that was just clicked. Then it will go to the top parent element which is body. if there is any click handle in body, the browser will call it. after checking the body element, it will look at the second top parent element which is div element. This process will repeat until the browser gets down to the button element at the very bottom. Once it sees the button element, Phase One- Capturing will be over. Most of the time we ignore this phase. This code ignores this phase

document.addEventListener('click',handleClick)

如果你想涉及到这一阶段,你必须这样写

document.addEventListener('click',handleClick,true)

当我们需要检测目标之外的点击时,我们就需要这个阶段。也许我们有一个打开的下拉菜单或者模态菜单如果用户点击了模态菜单或者下拉菜单之外的任何地方,我们想要关闭它

2-Target阶段

浏览器会查看被点击的按钮元素,如果按钮有事件处理程序,浏览器会调用它。

3-气泡阶段

与捕获阶段相反,在这个阶段,浏览器将从直接的父元素(在这种情况下是div元素)开始这个过程,然后它将访问body元素。这段代码将为气泡阶段设置事件处理程序

document.addEventListener('click',handleClick,false)