关于DOM2级事件的事件捕获和事件冒泡

DOM2级事件中addEventListener的执行机制,多个addEventListener同时添加时的执行先后规律:

W3C的DOM事件触发分为三个阶段:
①、事件捕获阶段,即由最顶层元素(一般是从window元素开始,有的浏览器是从document开始,至于其中的差别我稍后会更新)开始,逐次进入dom内部,最后到达目标元素,依次执行绑定在其上的事件
②、处于目标阶段,检测机制到达目标元素,按事件注册顺序执行绑定在目标元素上的事件。
③、事件冒泡阶段,从目标元素出发,向外层元素冒泡,最后到达顶层(window或document),依次执行绑定再其上的事件。

在addEventListener中,利用第三个参数控制其是从哪个阶段开始,“true”是从捕获阶段开始,而“false”则是跳过捕获阶段,从冒泡阶段开始。 看一个简单的例子:

 1 <script type="text/javascript">
 2 window.onload=function(){
 3     var outer = document.getElementById("outer");
 4     var inner = document.getElementById(‘inner‘);
 5
 6 outer.addEventListener("click",   function(){
 7       alert("1");
 8     }
 9 , true);
10
11  inner.addEventListener("click",      function(){
12       alert("2");
13      }
14 , true);
15
16  outer.addEventListener("click",
17      function(){
18         alert("3");
19     }
20 ,false)
21 }
22 </script>
23
24 <body>
25     <div id="outer">
26         <div id="inner"></div>
27     </div>
28 </body>

  在这个例子里,如果我们点击内层元素inner,那么处于捕获阶段的1最先弹出,接下来是目标元素2弹出,最后是处于冒泡阶段的3弹出,即:1,2,3. 即使在代码里变换三个绑定事件的顺序,只要点击的是inner,这个执行顺序就不会变。

那么问题来了,如果点击的是外层outer的话呢?

要明白这个问题,我们必须明确一点:目标事件在哪一层,事件流就在哪一层回流,即使在outer事件下还有许多子孙节点,事件流都不会在outer之后往内流,此时,inner上的事件不会被触发,因此在这段代码中,只会弹出1和3。

那么这两个数字哪个先弹呢?由于此时事件处于第二阶段,即“处于目标阶段”,弹出顺序取决的也不再是捕获或冒泡,而是谁在代码中先注册,因此,在这段代码中,弹出的是:1→3.

综上所述,事件在DOM中的执行顺序为:外层捕获事件→内层捕获事件→先注册的目标事件→后注册的目标事件→内层冒泡事件→外层冒泡事件

让我们再看个例子来加深这个概念:

 1 <script type="text/javascript">
 2 window.onload=function(){
 3     var outer = document.getElementById("outer");
 4     var inner = document.getElementById(‘inner‘);
 5     var oBox=document.getElementById(‘box‘);
 6
 7     oBox.addEventListener("click",function(){
 8         alert(‘1‘);
 9     },true)
10     oBox.addEventListener("click",function(){
11         alert(‘4‘);
12     },false)
13
14
15     outer.addEventListener("click", function(){
16       alert("2");
17     }, true);
18
19
20     inner.addEventListener("click",function(){
21         alert(‘3.2‘)
22     },false)
23
24
25     inner.addEventListener("click", function(){
26       alert("3.1");
27      }, true);
28
29 }
30 </script>
31
32 <body>
33     <div id="box">
34         <div id="outer">
35             <div id="inner"></div>
36         </div>
37     </div>
38 </body>

在这段代码里,box上的捕获事件最先执行,然后是outer上的捕获事件,然后是inner上先注册的事件,然后是inner上后注册的事件,最后是box上的冒泡事件 弹出顺序为:1→2→3.2→3.1→4

补充一点,在ie8-中,由于addEventLister不起作用,我们使用attachEvent方法来绑定事件,此时在第二阶段,也就是处于目标阶段,如果目标元素上绑定了两个事件,那么其执行顺序和addEventLister相反:谁后注册谁先执行.

接下来我们将问题再升级,如果dom0级事件和dom2级事件同时存在,那执行顺序会是怎样呢?

看下面的事例代码:

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title>dom2</title>
 6     <style>
 7         #box{
 8             width:500px;
 9             height:500px;
10             background-color: red;
11         }
12
13         #outer{
14             width:200px;
15             height:200px;
16             background-color: green;
17         }
18         #inner{
19             width:100px;
20             height:100px;
21             background-color: yellow;
22         }
23     </style>
24 </head>
25 <body>
26     <div id="box">
27         <div id="outer">
28             <div id="inner"></div>
29         </div>
30     </div>
31 </body>
32
33 <script type="text/javascript">
34     window.onload = function () {
35
36         var outer = document.getElementById("outer");
37         var inner = document.getElementById(‘inner‘);
38         var oBox = document.getElementById(‘box‘);
39
40         oBox.addEventListener("click", function () {
41             alert(‘oBox-Dom2冒泡‘);
42         }, false);
43
44         oBox.addEventListener("click", function () {
45             alert(‘oBox-Dom2捕获‘);
46         }, true);
47
48         outer.addEventListener("click", function () {
49             alert("outer-Dom2冒泡");
50         }, false);
51
52         outer.addEventListener("click", function () {
53             alert("outer-Dom2捕获");
54         }, true);
55
56         outer.onclick=function(){
57             alert("outer-dom0 click! ");
58         }
59
60         inner.addEventListener("click", function () {
61             alert(‘inner-Dom2冒泡‘);
62         }, false);
63
64         inner.addEventListener("click", function () {
65             alert("inner-Dom2捕获");
66         }, true);
67     }
68 </script>

此案例中,我将outer的div在捕获阶段和冒泡阶段都绑定了点击事件,同时还在绑定了dom0级的点击事件处理函数,这时如果我们点击inner,我们会发现,事件的执行顺序是这样的  oBox-Dom2捕获--> outer-Dom2捕获 --> inner-Dom2冒泡 -->  inner-Dom2捕获 --> outer-Dom2冒泡 --> outer-dom0 click! --> oBox-Dom2冒泡 由此我们可以得出一个结论:当绑定dom0级事件元素不是目标元素时,那么绑定dom0级事件的处理是在冒泡阶段处理并按事件注册的先后顺序执行(W3C先注册的先执行) ,如果绑定dom0级事件的元素是目标元素时,则不论是捕获阶段绑定的处理函数还是冒泡阶段绑定的处理函数以及dom0级事件处理函数,他们的执行顺序都是按照注册的顺序执行(W3C先注册的先执行) 。

时间: 2024-12-08 18:44:27

关于DOM2级事件的事件捕获和事件冒泡的相关文章

整理之DOM事件阶段、冒泡与捕获、事件委托、ie事件和dom模型事件、鼠标事件

整理之DOM事件阶段 本文主要解决的问题: 事件流 DOM事件流的三个阶段 先理解流的概念 在现今的JavaScript中随处可见.比如说React中的单向数据流,Node中的流,又或是今天本文所讲的DOM事件流.都是流的一种生动体现.用术语说流是对输入输出设备的抽象.以程序的角度说,流是具有方向的数据. 事件流分事件冒泡与事件捕获 在浏览器发展的过程中,开发团队遇到了一个问题.那就是页面中的哪一部分拥有特定的事件? 可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其

javascript -- 事件捕获,事件冒泡

使用js的时候,当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,单击子元素时,父元素的onclick事件也会被触发.js里称这种事件连续发生的机制为事件冒泡或者事件捕获. 为什么会有事件冒泡,又有捕获呢?应为当初IE浏览器和Natscape浏览器分别对自己浏览器的事件采用了不同的发生机制,IE浏览器采用了冒泡型:定义有相同事件的嵌套元素,当事件被触发时,子元素拥有优先权,即从里向外发生,像水里的泡泡一样从里向外冒.而Netscape采用了相反的做法,即捕获型,父元素拥有优先权

javascript中的事件冒泡、事件捕获和事件执行顺序

谈起JavaScript的 事件,事件冒泡.事件捕获.阻止默认事件这三个话题,无论是面试还是在平时的工作中,都很难避免. DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应用有着相当大的影响.这两种事件流分别是捕获和冒泡.和许多Web技术一样,在它们成为标准之前,Netscape和微软各自不同地实现了它们.Netscape选择实现了捕获事件流,微软则实现了冒泡事件流.幸运的是,W3C决定组合使用这两种方法,并且大多数新浏览器都遵循这两种事件流方式. 1事件传播--冒泡与捕

WPF事件(一)内置路由事件

原文:WPF事件(一)内置路由事件 Windows是消息驱动的操作系统,运行其上的程序也遵照这个机制运行,随着面向对象开发平台日趋成熟,微软把消息机制封装成了更容易让人理解的事件模型,一个事件包含3个关键点:事件的拥有者.事件的响应者.事件的订阅关系 为了降低由事件订阅带来的耦合度和代码量,WPF推出了路由事件机制,路由事件与传统的直接事件的区别在于,直接事件激发时发送者直接将消息通过事件订阅交送给事件响应者,事件响应者使用其事件处理器方法対事件的发生做出响应.驱动程序逻辑按客户需求运行,而路由

JS:Html事件处理程序 vs DOM0级事件处理程序 vs DOM2级事件处理程序

1.HTML事件处理程序 某个元素支持的某种事件,可以通过一个与相应事件处理程序同名的HTML特性指定.这个特性的值应该是能够执行的JS代码.例如:按钮单击是要执行一些js代码,可以像下面: <input type="button" value="click me" onclick="showMessage()" /> 在js中就可以像下面一样处理: <script> function showMessage(){ ale

DOM0、DOM2级事件

JavaScript DOM0.DOM2级事件 1.DOM0级事件:on+事件类型 在html行内直接绑定,也就是通过行内js绑定的例如<span onclick="alert('1')">第一项</span> 在js中绑定例如://<span onclick="alert('2')">第一项</span> var Ospan=document.getElementsByTagName('span')[0];Ospan

Dom0级事件和Dom2级事件

1.Dom0级事件: 注册obj.onclick=function () {}; (1.使用简单,2.跨浏览器): 删除obj.onclick=null; 2.Dom2级事件(比0级优点:多个处理函数不会被覆盖): 成员 -> addEventListener注册事件   removeEventListener移出事件: 三个参数 -> 1事件名(都不能带on),2处理函数,3布尔值涉及嵌套元素的事件触发顺序(true按捕获流的顺序调用,false按事件冒泡流的顺序调用): (IE下用atta

2015-03-12——简析DOM2级事件

DOM2级事件 事件的几种类型:对象事件,鼠标事件,键盘事件,表单事件,W3CDOM事件,以及针对浏览器的事件. 对象事件:window对象,也是javascript对象.load  适用于window对象,页面需要的所有图像文件都载入完成才触发.unload  适用于window对象,页面被关闭之前捕获最后一瞬间的信息.error  适用于window对象和图像对象.图像一旦设置src属性,就开始载入图像.abort  在图像完全载入之前,因浏览器停止载入页面导致图像载入失败时触发.通常发生在

事件流程以及dom2级事件绑定

事件流程分为三个阶段:捕获阶段.目标阶段.冒泡阶段. 捕获阶段:事件从最顶层元素开始执行,一层层往下,直到精确元素. 目标阶段:事件在精确元素上执行. 冒泡阶段:事件从精确元素开始执行,一层层往上,直到顶层元素(注:高级浏览器的顶层元素是window,ie8以下的浏览器顶层元素是document)  DOM2级事件绑定方式   高级浏览器绑定方式: 元素.addEventListener(type, handler, boolean);             //绑定 type 事件类型字符串