DOM事件流的概念
当某个事件发生时,事件会在元素节点之间按照特定的顺序传播,这个传播过程称为DOM事件流。
DOM事件流分为两个阶段--捕获阶段、冒泡阶段。捕获阶段简单来说就是从整个页面(即document)开始到html--body--div--ul--li...。即根据元素的嵌套顺序依次传递事件,直到找到触发该事件的元素为止。而冒泡阶段则为捕获阶段的逆过程,即从触发事件的元素开始根据元素的嵌套顺序找到document为止。即除触发事件的元素外,其余每个节点都被访问两次,从而会出现事件触发的先后顺序问题。
注意:JavaScript代码只能执行捕获或冒泡的其中一个阶段。
常见的事件绑定方法在DOM事件流的运用
onclick:只能使用冒泡阶段
attachEvent:只能使用冒泡阶段
addEventListener:第三个参数决定使用哪个阶段。第三个参数若为true,则使用捕获阶段,若为false(默认),则使用冒泡阶段。若不输入第三个参数默认为false。
以addEventListener为例:
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('click', function() {
alert('father');
}, false);
son.addEventListener('click', function() {
alert('son');
}, false);
</script>
此时点击中间蓝色区域,网页弹出的内容依次为son、father
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('click', function() {
alert('father');
}, true);
son.addEventListener('click', function() {
alert('son');
}, true);
</script>
而此时点击中间蓝色区域,网页弹出的内容依次为father、son
原因分析:
代码1的addEventListener的第三个参数皆为false,即两事件的触发皆处于冒泡阶段,根据事件流原理,冒泡阶段从子级元素向父级元素传递,即先触发son盒子的事件,后触发father盒子的事件。
代码2则反之,两事件的触发皆处于捕获阶段,从父级元素向自己元素传递,即先触发father盒子的事件,后触发son盒子的事件。
则根据此原理,在实际开发中我们可以通过addEventListener的第三个参数控制嵌套元素的事件触发的先后顺序。
特殊情况
某些事件是没有冒泡阶段的,例如onblur、onfocus、onmouseenter、onmouseleave等。