DOM中的事件流

2017-02-24

今天在写事件监听器时,突然想起addEventListener方法是有一个非必填的参数,用来定义事件的执行阶段, 捕获还是冒泡,true是捕获还是false是捕获,记忆有些模糊了…

先看一段代码

HTML结构如下:

1
2
3
4
5
<div id="wrapper">
<div id="content">
<button id="btn"></button>
</div>
</div>

JS代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
document.addEventListener('click', function(e) {
alert('document');
},true);
document.querySelector('#wrapper').addEventListener('click', function(e) {
alert('wrapper');
},false);

document.querySelector('#content').addEventListener('click', function(e) {
alert('content');
},true);

document.querySelector('#btn').addEventListener('click', function(e) {
alert('btn');
},false);

提问: 那么,点击按钮后,alert的顺序是怎样的?

如果你的答案是 document content btn wrapper,那么下面的废话可以不用看了

先捕获,后冒泡

首先,要知道addEventListener方法的第二个参数

  • 设置true,是定义该事件在捕获阶段执行,
  • 设置false,或者不设置,事件在冒泡阶段执行

事件捕获(Capture Phase)

事件捕获是最早是Netscape对事件流的实现:当事件被触发的时候,从根节点一个个去检查是否有绑定事件,如果就触发事件,没有就下一个节点,直到点击的那个元素的父元素为止

当事件捕获结束后,再执行触发事件的元素的事件

事件冒泡(Bubbling Phase)

事件冒泡最早是IE对事件流的实现:当事件被触发后,当前元素上绑定的事件立即执行

然后事件开始冒泡,先检查这个元素的父元素,如有绑定事件就触发事件,没有就往上走,直至文档的根节点

W3C一统天下

W3C在规范中包含这两种事件机制,用一句话说明: 先捕获,后冒泡

最后引用规范中的这张图来说明

答案解释

当按钮按下后,

第一阶段:

先捕获,那么有两个事件是设置在捕获阶段执行的,而且捕获是有外层到里的顺序,所以,document先执行,然后到content,捕获阶段结束

第二阶段:

触发事件的元素btn执行

第三阶段:

开始冒泡,离btn最近的一个父节点开始往外走,然后wrapper上有绑定事件,所以wrapper触发,继续往外走,没有事件了,结束

参考链接: