当咱们给元素绑定好单击事件,单击这个元素,就会执行相应的代码,可是若是这个元素的父元素、祖先元素都绑定了单击事件,他们会执行吗?他们的执行顺序是什么呢?javascript
能够尝试把页面理解为一个二维的平面,想象有一张白纸,咱们在这张纸上画下了一层一层的同心圆,当咱们用手指按住最内的圆圈时,也按住了纸上全部的同心圆,也按住了整张纸。因此单击事件不单单发生在被击中的元素上,换句话说,当咱们用鼠标单击其中一个元素时,你也是在单击元素的容器,甚至一层一层向外传递(也能够是向内),甚至是在单击整个页面。css
定义:描述的是从页面中接收事件的顺序html
IE的事件流叫作事件冒泡,即事件开始时有最具体的元素(文档中嵌套层次最深的那个节点)接收,而后逐级向上传播到较为不具体的节点,直到document对象。java
下图展现了事件冒泡的过程浏览器
Netscape Communicator团队提出的另外一种事件流叫作事件捕获。事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
下图展现了事件捕获的过程函数
“DOM2级事件”规定的事件流包括三个阶段:事件捕获、处于目标阶段和事件冒泡阶段。发生的顺序是事件捕获阶段==>目标阶段==>事件冒泡阶段测试
了解了基本概念,来用代码测试一下。spa
html3d
<div id="first"> <div id="second"> <div id="third"></div> </div> </div>
css代理
#first{ width:200px; height:200px; margin:0 auto; background:red; border:1px solid #ccc; } #second{ width:150px; height:150px; margin:24px auto; background:yellow; border:1px solid #ccc; } #third{ width:100px; height:100px; margin:24px auto; background:blue; border:1px solid #ccc; }
js
//第三个参数设为false,将事件处理程序添加到冒泡阶段 first.addEventListener('click',function(e){ var target=e.target; console.log('红色框'); },false); second.addEventListener('click',function(e){ var target=e.target; console.log('黄色框'); },false); third.addEventListener('click',function(e){ var target=e.target; console.log('蓝色框'); },false);
单击嵌套最深的元素,控制台输出结果:
由于最内层元素自己有一个单击事件,它的父元素及祖先元素分别有一个单击事件,因此单击最内层元素位置,同时单击了三个元素,启动了三次事件处理程序。由于三个事件都是冒泡阶段执行,因此控制台输出的顺序为最内层的蓝色框——>中间的黄色框——>外层的红色框。
将第三个参数都改成true,控制台输出以下:
这时事件执行顺序改成从最外层的元素——>中间元素———>最内层的元素
咱们能够很直观的看到事件同时都在冒泡阶段或捕获阶段执行的顺序,但若是这三个元素的事件处理程序在不在同一阶段执行呢?在看到结果以前能够试试预想一下它们的执行顺序。
咱们能够试一试将红色框与蓝色框的第三个参数设为false,黄色框的参数设为true。输出结果以下:
单击蓝色框后,开始事件捕获阶段:
从最外层的document对象(浏览器实际上是从window对象开始的)向内捕获事件,路过红色框时,查看到红色框有事件,可是红色框说:“我是在冒泡阶段执行,如今是捕获阶段,等你回来再说吧。”接下来是黄色框:“我在捕获阶段执行,就是如今执行!在控制台输“黄色框”吧~~”
接下来到达目标阶段:
“DOM2级事件”规范要求捕获阶段不会涉及事件目标即咱们点击的那个最具体的元素,但IE九、Chrome等浏览器都会在捕获阶段触发事件对象上的事件。执行目标对象的事件函数,控制台输出“蓝色框”。
最后是冒泡阶段:
由目标对象向外传递,到达黄色框,黄色框说:“我在捕获阶段执行过了,你走吧...”而后到达红色框,红色框说:“你终于回来了,如今就执行个人事件!”控制台输出“红色框”。而后继续向外传播,直到到达document对象后中止。
其余:更改了元素绑定事件代码的顺序,执行顺序也和上面表现的一致。
将事件添加到什么阶段执行,事件就会在触发事件后,在DOM事件流中相应的阶段执行。
大多数状况下,都是将事件处理程序添加到事件流的冒泡阶段,这样能够最大程度的兼容各类浏览器(事件冒泡由IE提出),最好只在须要在事件到达目标以前截获它的时候将事件处理程序添加到捕获阶段。
一个元素绑定事件时须要考虑到父元素及祖先元素的事件,应该注意它们之间的事件执行顺序及执行结果,因此推荐在合适的状况下使用事件代理。