思考问题:
html中的标签都是相互嵌套的,我们可以将元素想象成一个盒子装一个
盒子,document是最外面的大盒子。
当你单击一个div时,同时你也单击了div的父元素,甚至整个页面。
那么是先执行父元素的单击事件,还是先执行div的单击事件 ?
要搞清楚这个问题,就需要学习事件流
- 事件流描述的是从页面中接收事件的顺序。(事件流,事件传播的流程)
- 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。
W3C制定的标准----先捕获再冒泡
1、DOM 事件流会经历3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
含义:事件发生时会在元素节点之间按照特定的顺序传播,这个过程称为事件流
2、事件冒泡案例
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// 如果addEventListener 第三个参数是 true 那么则处于捕获阶段
// 顺序为:document -> html -> body -> father -> son
// 如果addEventListener 第三个参数是 false 或者 省略 那么处理冒泡阶段
// 顺序为:son -> father ->body -> html -> document
var son = document.querySelector('.son');
// 给son注册单击事件
son.addEventListener('click', function() {
alert('son');
}, false);
// 给father注册单击事件
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
// 给document注册单击事件,省略第3个参数
document.addEventListener('click', function() {
alert('document');
})
</script>
注意:
- JS 代码中只能执行捕获或者冒泡其中的一个阶段。
- onclick 和 attachEvent 只能得到冒泡阶段。(理解:只在冒泡阶段触发)
- addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
- 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件。