事件捕获与事件冒泡

前言

这里首先要先讲一下什么是事件、事件流:
事件:浏览器执行的动作,如click、load等。
事件流:事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。

正文

1
2
3
<div id="outer">
<div id="inner">Click me!</div>
</div>

上面代码中,如果两个元素都绑定了click事件,当点击后函数会怎样触发呢?

为了解决这个问题微软和网景提出了两种几乎完全相反的概念,事件冒泡事件捕获

事件冒泡:事件会从最内层的元素开始发生,一直向上传播,直到document对象。
div -> body -> html -> document

事件捕获:事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
document -> html -> body -> div

addEventListener

为了更清楚的理解事件捕获与事件冒泡,进一步了解addEventListener方法。
addEventListener方法用来为一个特定的元素绑定一个事件处理函数,是JavaScript中的常用方法。addEventListener有三个参数:

1
element.addEventListener(event, function, useCapture)

event:字符串,指定事件名,如click、blur等。
function:指定事件触发时执行的函数。
useCapture: 可选,Boolean,指定事件是否在捕获或冒泡阶段执行,true-事件句柄在捕获阶段执行,false-默认,事件句柄在冒泡阶段执行。

测试

1
2
3
4
5
6
7
8
9
10
11
this.$outerDiv = document.getElementById('outerDiv');
this.$innerDiv = document.getElementById('innerDiv');
this.$outerDiv.addEventListener('click', () => {
alert('I am outer div');
}, true);
this.$innerDiv.addEventListener('click', () => {
alert('I am inner div');
}, true);
<div id="outer">
<div id="inner">Click me!</div>
</div>

useCapture为true,事件句柄在捕获阶段执行,所以alert顺序为 I am outer div , I am inner div。
如果useCapture为false,事件句柄在冒泡阶段执行,顺序与上方相反。实践操作

如果想终止捕获或冒泡。添加event.stopPropagation()方法。