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

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

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

 1 <script type="text/javascript">
 2 window.οnlοad=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.οnlοad=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.οnclick=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先注册的先执行) 。

转载于:https://www.cnblogs.com/guangyan/p/6686013.html

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

  1. JavaScript事件捕获与事件冒泡原理 IE和DOM之间存在哪些主要差别

    事件--怎样使用事件以及IE和DOM事件模型之间存在哪些主要差别. (1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. IE 5.5: div -&g ...

  2. js中事件捕获和事件冒泡

    全栈工程师开发手册 (作者:栾鹏) js系列教程8-事件操作全解 js中事件捕获和事件冒泡 其实不仅在js中,在面向对象的编程语言中或多或少涉及到这个问题.js编程的事件全解,你可以到我的主页,这里给 ...

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

    谈起JavaScript的 事件,事件冒泡.事件捕获.阻止默认事件这三个话题,无论是面试还是在平时的工作中,都很难避免. DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应用有 ...

  4. javascript --- DOM0级、DOM2级、跨浏览器 的事件处理程序

    DOM0级事件处理程序: // 使用DOM0级方法指定的事件处理程序被认为是元素的方法 // 这个时候的事件处理程序是在元素的作用域中运行: <div id = "myBtn" ...

  5. 【20190226】JavaScript-知识点记录:dom0级事件,dom2级事件

    DOM0级事件处理程序: 通过将元素的事件处理程序属性(如onclick)的值设置为一个函数来指定事件处理程序的方法称为DOM0级方法,它被认为是元素的方法,这时候的事件处理程序是在元素的作用域中运行 ...

  6. DOM-8 【兼容】冒泡捕获流、事件与事件源对象、事件委托

    事件流 1. 含义 描述从页面中接收事件的顺序 2. 分类 IE提出的 事件冒泡流 Event Bubbling Netscape提出的 事件捕获流 Event Capturing 3. 阶段 事件捕 ...

  7. js监听多个事件_JavaScript中的事件与异常捕获解析

    这篇文章主要给大家介绍了关于JavaScript中事件与异常捕获的相关资料,文中通过示例代码介绍的非常详细,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批 ...

  8. JavaScript(js)事件冒泡、事件捕获、事件委托详解

    JavaScript(js)事件冒泡.事件捕获.事件委托详解 1.什么是事件 JavaScript和HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口发生的一些特定的交互瞬间.可以使用监听 ...

  9. 使用Python,OpenCV捕获关键事件,并进行视频剪辑

    使用Python,OpenCV捕获关键事件,并进行视频剪辑 1. 效果图 2. 原理 2.1 步骤 2.2 如何找到HSV空间值呢? [[[60 255 255]]] 3. 源码 3.1 keycli ...

最新文章

  1. MySQL:互联网公司常用分库分表方案汇总!
  2. linux webrtc浏览器,WebRTC 浏览器支持
  3. Golang 优化之路-空结构[转]
  4. 第12章:Linux服务管理
  5. 微服务之迷思--转几位大牛的文章
  6. java同步读写,关于java:Collections中的synchronizedMap方法是否同步读写操作
  7. 8051 管脚定义_8051微控制器的引脚说明
  8. pythonweb接口优化_python-web后台限制接口调用频率
  9. android 修改 选择壁纸来源,修改android选择壁纸来源列表
  10. objective-C 数据类型转换
  11. Jensen不等式初步理解及证明
  12. 英特尔®以太网700系列的动态设备个性化
  13. java里面getsource_java e.getsource
  14. linux 邮件文件名 病毒,linux-qmail 病毒/垃圾邮件处理
  15. 我的IT之路------来自黑马程序员
  16. Beta周王者荣耀交流协会第六次会议
  17. vs写c语言快捷键,vs快捷键
  18. 8-详解前缀树贪心算法N皇后问题
  19. bsfl ecx,ecx
  20. 简单教学 apache 配置 Expire/Cache-Control 头

热门文章

  1. Linux添加文件命令
  2. PHP Deprecated: Function ereg_replace() is deprecated in 的解决方法
  3. Python断言方法:assert
  4. 19-for循环语句
  5. Python爬虫学习系列教程-----------爬虫系列 你值的收藏
  6. SQL实战篇:SQL解决近X天的问题
  7. VTK使用矢量数据弯曲几何体
  8. 一文看懂如何搭建AI应用:10周学会深度学习,还赢下5千美元
  9. 数组转换成json key-value形式
  10. CentOS 6.X安装LAMP最高版本环境