首页 > 代码库 > 粗浅的总结下事件流

粗浅的总结下事件流

什么是事件流?以及为什么要有事件流?

简单的说,事件流就是,确认触发条件满足时,事件对应函数的调用顺序。举个例子,鼠标光标在某个按钮上点击了,按钮又绑定了mousedown事件,那么其对应的函数就会调用。而其实,光标落下的位置也在document、window的范围内,或许还可能在其他元素的和模型内。如果这些元素也都绑定了mousedown事件,那么哪个元素的mousedown事件对应的函数先调用呢?这就需要确认一个发生的顺序问题。

具体的说,事件流分为三个阶段,即捕获阶段、目标(处理)阶段、冒泡阶段。网上随便找了一张示意图,如下:

技术分享

 

其实这张图以及网上很多说法(比如百度百科DOM事件流)都不是很严谨,漏掉了window对象。事件流应该是从window开始,在window对象结束(如果捕获阶段和冒泡阶段,window都绑定了事件的话)。估计是window对象通常只在冒泡阶段绑定load事件吧,不谈也没什么影响。

 

一个演示事件流的例子

下图中,在鼠标单击金黄色span区域时,控制台对应打印出日志。

技术分享

源代码在这里:

技术分享
 1 <!DOCTYPE html>
 2 <html id="html">
 3     <head>
 4         <meta charset="UTF-8">
 5         <title></title>
 6         <style>
 7             div{
 8                 width: 200px;
 9                 height: 200px;
10                 font-size: 30px;
11                 color: #fff;
12                 background: green;
13             }
14             span{
15                 display: block;
16                 width: 100px;
17                 height: 100px;
18                 background: goldenrod;
19                 color: #fff;
20                 font-size: 30px;
21             }
22             body{
23                 border: 1px solid #000;
24             }
25         </style>
26         <script>
27             
28             window.onload=function(){
29                 var div=document.getElementById("div");
30                 var span=document.getElementById("span");
31                 var html=document.getElementById("html");
32                 var body=document.getElementById("body");
33                 var head=document.getElementById("head");
34 
35                 body.addEventListener(click,function(){console.log(body冒泡)},false);
36                 html.addEventListener(click,function(){console.log(html冒泡)},false);
37                 window.addEventListener(click,function(){console.log(window冒泡)},false);
38                 document.addEventListener(click,function(){console.log(document冒泡)},false);
39                 div.addEventListener(click,function(){console.log(div冒泡)},false); 
40                 span.addEventListener(click,function(){console.log(span冒泡)},false);
41                 span.addEventListener(click,function(){console.log(span捕获)},true);
42                 document.addEventListener(click,function(){console.log(document捕获)},true);
43                 window.addEventListener(click,function(){console.log(window捕获)},true);
44                 html.addEventListener(click,function(){console.log(html捕获)},true);
45                 body.addEventListener(click,function(){console.log(body捕获)},true);
46                 div.addEventListener(click,function(){console.log(div捕获)},true);
47             };
48         </script>
49     </head>
50     <body id="body">
51         <div id="div">div
52             <span id="span">span</span>
53         </div>
54     </body>
55 </html>
View Code

结合图片和代码,可以发现两个问题:

1、代码中故意将打印带有“冒泡”字样的语句写在了前面,而且也没有按“window捕获->document捕获->html捕获->body捕获->div捕获->span捕获->span冒泡->div冒泡->body冒泡->html冒泡->document冒泡->window冒泡”这样的顺序,但是控制台中打印的日志基本上与事件流的顺序一致。

2、第二个问题,也就是控制台中打印的日志与事件流的顺序不一致的地方,为什么“span冒泡”在“span捕获”前面呢?因为,触发的是span绑定的事件,那么span绑定的事件就在目标阶段触发。触发顺按照代码中书写顺序来。本例中,即

 span.addEventListener(‘click‘,function(){console.log(‘span冒泡‘)},false); 

 span.addEventListener(‘click‘,function(){console.log(‘span捕获‘)},true); 前面。

 

补充说明:

addEventListener绑定事件语法: 对象.addEventListener(事件名称,事件绑定函数,布尔值)

布尔值取值说明:
* true 事件是在捕获的阶段发生的
* false 事件是在冒泡的阶段发生的(缺省值)

 

技术分享
本作品采用知识共享署名 4.0 国际许可协议进行许可。

粗浅的总结下事件流