事件捕获 or 事件冒泡

941 阅读2分钟

事件流描述的就是从页面中接收事件的顺序。而IENetscape提出了完全相反的事件流概念。IE事件流是事件冒泡,而Netscape的事件流就是事件捕获。

事件捕获

事件捕获的思想是不太具体的节点应该更早的接收到事件,而在最具体的节点应该最后接收到事件。事件捕获的用以在于 事件到达预定目标之前 捕获它。从window开始捕获(尽管DOM2级事件规范要求从document)。由于老版本浏览器不支持,所以很少有人使用事件捕获。

事件冒泡

IE的事件流叫做事件冒泡。即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。所有现代浏览器都支持事件冒泡,并且会将事件一直冒泡到window对象。

实例

还是来具体实操吧

HTML:

<html>
  <body>
    <div class="div1">
      div1
      <div class="div2">
        div2
        <div class="div3">
          div3
        </div>
      </div>
    </div>
  </body>
</html>

CSS:

.div1 {
  position: relative;
  width: 300px;
  height: 300px;
  background: grey;
}

.div2 {
  width: 200px;
  height: 200px;
  background: yellow;
}

.div3 {
  width: 100px;
  height: 100px;
  background: red;
}

.div2,
.div3 {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%)
}

JS:

function getElement(className) {
  return document.querySelector(className)
}

const div1 = getElement('.div1');
const div2 = getElement('.div2');
const div3 = getElement('.div3');

div1.addEventListener('click', () => {
   console.log('bubble event: div1 click')
});
div1.addEventListener('click', () => {
   console.log('capture event: div1 click')
}, true);

div2.addEventListener('click', () => {
   console.log('bubble event: div2 click')
});
div2.addEventListener('click', () => {
   console.log('capture event: div2 click')
}, true);

div3.addEventListener('click', () => {
   console.log('bubble event: div3 click')
});
div3.addEventListener('click', () => {
   console.log('capture event: div3 click')
}, true); 

点击红色区域,会输出哪些log信息?

"capture event: div1 click"

"capture event: div2 click"

"bubble event: div3 click"

"capture event: div3 click"

"bubble event: div2 click"

"bubble event: div1 click"

解析

一共3个div,每个div我们都分别在它的冒泡阶段和捕获阶段注册了监听器,所以当我们点击红色区域时(此时事件预定目标为'div3')

第一阶段:事件捕获阶段(到达预订目标(div3)之前) 依次输出

"capture event: div1 click"

"capture event: div2 click"

第二阶段:目标阶段(div3) 依次输出

"bubble event: div3 click"

"capture event: div3 click"

第三阶段:事件冒泡阶段 (到达预订目标(div3)之后) 依次输出

"bubble event: div2 click"

"bubble event: div1 click"

思考题

在事件到达 预订目标div3 时,为什么先输出"bubble event: div3 click"再输出"capture event: div3 click"

Demo 

codepen.io/aaron-gym/p…

补充知识点:

addEventListener方法属于DOM二级,使用时如果不提供第三个参数,默认是在冒泡阶段触发

有问题的小伙伴可以留言,欢迎交流