谈起JavaScript的 事件,事件冒泡、事件捕获、阻止默认事件这三个话题,无论是面试还是在平时的工作中,都很难避免。

DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应用有着相当大的影响。这两种事件流分别是捕获和冒泡。和许多Web技术一样,在它们成为标准之前,Netscape和微软各自不同地实现了它们。Netscape选择实现了捕获事件流,微软则实现了冒泡事件流。幸运的是,W3C决定组合使用这两种方法,并且大多数新浏览器都遵循这两种事件流方式。

1事件传播——冒泡与捕获

默认情况下,事件使用冒泡事件流,不使用捕获事件流。然而,在Firefox和Safari里,你可以显式的指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true。

概念:

事件冒泡:事件最开始由最具体的元素接收(文档层次中嵌套最深的那个节点),然后逐级向上传播最不具体的节点(document)。

事件捕获:事件由最不具体的元素接收,最后传播至最具体的元素。

事件冒泡代码实例:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title>事件冒泡</title>
</head>
<body><div id="e"><input id="btn" type="button" value="按钮"></div><script type="text/javascript">var e = document.getElementById('e');var btn = document.getElementById('btn');e.onclick = function (){alert("你点击了div");};btn.onclick = function(){alert("你点击了button");}</script>
</body>
</html>

当我点击了按钮时候,运行 --你点击了button ——你点击了div,这就是事件冒泡。

事件捕获代码:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title>事件冒泡</title>
</head>
<body><div id="e"><input id="btn" type="button" value="按钮"></div><script type="text/javascript">var e = document.getElementById('e');var btn = document.getElementById('btn');e.addEventListener('click',function(){alert('你点击了div');},true);btn.addEventListener('click',function(){alert('你点击了button');},true);</script>
</body>
</html>

当我点击了按钮时候,运行 --你点击了div ——你点击了button,这就是事件捕获。

(1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。

IE 5.5: input -> div -> body -> document

IE 6.0: input -> div -> body -> html -> document

Mozilla 1.0: input -> div -> body -> html -> document -> window

事件冒泡见下图:

(2)捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。

事件捕获见下图:

(3)DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在document对象结束。

一般来说事件冒泡机制,用的更多一些,所以在IE8以及之前,IE只支持事件冒泡。IE9+/FF/Chrome这2种模型都支持,可以通过addEventListener((type, listener, useCapture)的useCapture来设定,useCapture=false代表着事件冒泡,useCapture=true代表着采用事件捕获。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。

2DOM事件流

DOM事件流我也不知道怎么解释,个人感觉就是事件冒泡和事件捕获的结合体,直接看图吧

DOM事件流:将事件分为三个阶段:捕获阶段、目标阶段、冒泡阶段。先调用捕获阶段的处理函数,其次调用目标阶段的处理函数,最后调用冒泡阶段的处理函数。

<script>window.onload = function(){var outA = document.getElementById("outA");  var outB = document.getElementById("outB");  var outC = document.getElementById("outC");  // 目标(自身触发事件,是冒泡还是捕获无所谓)outC.addEventListener('click',function(){alert("target");},true);// 事件冒泡outA.addEventListener('click',function(){alert("bubble1");},false);outB.addEventListener('click',function(){alert("bubble2");},false);// 事件捕获outA.addEventListener('click',function(){alert("capture1");},true);outB.addEventListener('click',function(){alert("capture2");},true);    };</script><body><div id="outA" style="width:400px; height:400px; background:#CDC9C9;position:relative;"><div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;"><div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div> </div></div>
</body>

当点击outC的时候,依次打印出capture1-->capture2-->target-->bubble2-->bubble1。到这里是不是可以理解addEventListener(type,handler,useCapture)这个API中第三个参数useCapture的含义呢?useCapture=false意味着:将事件处理函数加入到冒泡阶段,在冒泡阶段会被调用;useCapture=true意味着:将事件处理函数加入到捕获阶段,在捕获阶段会被调用。从DOM事件流模型可以看出,捕获阶段的事件处理函数,一定比冒泡阶段的事件处理函数先执行。

3事件函数执行先后顺序

<script>window.onload = function(){var outA = document.getElementById("outA");  var outB = document.getElementById("outB");  var outC = document.getElementById("outC");  // 目标(自身触发事件,是冒泡还是捕获无所谓)outC.addEventListener('click',function(){alert("target2");},true);outC.addEventListener('click',function(){alert("target1");},true);// 事件冒泡outA.addEventListener('click',function(){alert("bubble1");},false);outB.addEventListener('click',function(){alert("bubble2");},false);// 事件捕获outA.addEventListener('click',function(){alert("capture1");},true);outB.addEventListener('click',function(){alert("capture2");},true);};</script><body><div id="outA" style="width:400px; height:400px; background:#CDC9C9;position:relative;"><div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;"><div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div> </div></div>
</body>

点击outC的时候,打印顺序是:capture1-->capture2-->target2-->target1-->bubble2-->bubble1。由于outC是我们触发事件的目标对象,在outC上注册的事件处理函数,属于DOM事件流中的目标阶段。目标阶段函数的执行顺序:先注册的先执行,后注册的后执行。这就是上面我们说的,在目标对象上绑定的函数是采用捕获,还是采用冒泡,都没有什么关系,因为冒泡和捕获只是对父元素上的函数执行顺序有影响,对自己没有什么影响。如果不信,可以将下面的代码放进去验证。

此我们可以给出事件函数执行顺序的结论了:捕获阶段的处理函数最先执行,其次是目标阶段的处理函数,最后是冒泡阶段的处理函数。目标阶段的处理函数,先注册的先执行,后注册的后执行。

4阻止冒泡和捕获

默认情况下,多个事件处理函数会按照DOM事件流模型中的顺序执行。如果子元素上发生某个事件,不需要执行父元素上注册的事件处理函数,那么我们可以停止捕获和冒泡,避免没有意义的函数调用。前面提到的5种事件绑定方式,都可以实现阻止事件的传播。IE8以及以前可过 window.event.cancelBubble=true阻止事件的继续传播;IE9+/FF/Chrome通过event.stopPropagation()阻止事件的继续传播。

<script>window.onload = function(){var outA = document.getElementById("outA");  var outB = document.getElementById("outB");  var outC = document.getElementById("outC");  // 目标outC.addEventListener('click',function(event){alert("target");if(event.stopPropagation){event.stopPropagation();}else{event.cancelBubble = true;//IE阻止事件冒泡,true代表阻止
            }},false);// 事件冒泡outA.addEventListener('click',function(){alert("bubble");},false);// 事件捕获outA.addEventListener('click',function(){alert("capture");},true);        };
</script>
<div id="outA" style="width:400px; height:400px; background:#CDC9C9;position:relative;"><div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;"><div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div> </div></div>

当点击outC的时候,之后打印出capture-->target,不会打印出bubble。因为当事件传播到outC上的处理函数时,通过stopPropagation阻止了事件的继续传播,所以不会继续传播到冒泡阶段。

原文链接:http://lib.csdn.net/article/javascript/6265?knId=505

转载于:https://www.cnblogs.com/qianmojing/p/6253770.html

javascript中的事件冒泡、事件捕获和事件执行顺序相关推荐

  1. JavaScript权威设计--事件冒泡,捕获,事件句柄,事件源,事件对象(简要学习笔记十八)...

    1.事件冒泡与事件捕获 2.事件与事件句柄   3.事件委托:利用事件的冒泡技术.子元素的事件最终会冒泡到父元素直到跟节点.事件监听会分析从子元素冒泡上来的事件. 事件委托的好处:     1.每个函 ...

  2. vue 阻止事件冒泡,捕获方法

    要想了解 VUE 阻止事件冒泡和捕获方法,首先要了解一下 JS 事件和 JS 阻止事件冒泡,捕获方法 1. js 事件的三阶段 捕获阶段 目标阶段:执行当前对象的事件处理程序 冒泡阶段 2. js 阻 ...

  3. 事件冒泡、捕获?如何阻止

    事件冒泡 <style>div{color: white;font-size: 30px;}.content{width: 400px;height: 400px;background-c ...

  4. JS 中的事件冒泡与捕获

    本文来源:渔人 原文地址:http://yuren.space/blog/2016/10/16/事件冒泡与捕获/ 刚接触 JS 的那个时候,啥也不懂,只想着如何利用 Google.百度到的函数来解决实 ...

  5. JS 事件冒泡、捕获。学习记录

    作为一个转行刚到公司的新人,任务不多,这一周任务全部消灭,闲暇的一天也别闲着,悄悄的看起了书.今天写一下JS的事件冒泡.捕获. 也是今天看的内容有点多了,有些消化不了,就随手记录一下.纯属自我理解,如 ...

  6. JavaScript 中的内存和性能、模拟事件(读书笔记思维导图)

    由于事件处理程序可以为现代 Web 应用程序提供交互能力,因此许多开发人员会不分青红皂白地向页面中添加大量的处理程序.在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体 ...

  7. vue 阻止事件冒泡和捕获

    vue 阻止事件冒泡和捕获 @click.stop : 阻止事件冒泡 @click.prevent : 阻止事件默认行为 @click.self : 事件只作用在元素本身,而不是其子元素

  8. JS 事件冒泡整理 浏览器的事件流

    JavaScript与HTML的交互通过事件来实现.而浏览器的事件流是一个非常重要的概念.不去讨论那些古老的浏览器有事件捕获与事件冒泡的争议, 只需要知道在DOM2中规定的事件流包括了三个部分,事件捕 ...

  9. Js阻止事件冒泡和阻止默认事件

    js中阻止事件冒泡,阻止默认事件的方法,理解stopPropagation(),preventDefault(),return false的区别 1.event.stopPropagation()方法 ...

  10. JS、Vue、React阻止事件冒泡及阻止默认事件

    JS阻止事件冒泡及阻止默认事件解决方案: 1.event.preventDefault -- 阻止默认 Event 接口的 preventDefault()方法,告诉user agent:如果此事件没 ...

最新文章

  1. LAMP--Apache 禁止指定 user_agent
  2. 我知道今天是写总结的日子-所以买了一罐啤酒喝
  3. android日志收集存入mysql_rsyslog+analyzer+mysql实现日志收集展示
  4. 5 Handler与子线程
  5. PAT1052 卖个萌 (20 分)【别人的代码 借鉴从字符串中截取特定部分的思路】
  6. 十二. python面向对象主动调用其他类
  7. java 获取所有线程,Java 实例 - 获取所有线程
  8. 《2001太空漫游》50周年:一部电影和一整个时代
  9. [置顶] 金山云存储解决企业办公难题
  10. GBDT原理及利用GBDT构造新的特征-Python实现
  11. NSCharacterSet 去除NSString中的空格
  12. 我要写写集成https证书
  13. 手机html微信登录,添加手机APP微信登录支持,微信公众号单页应用网页授权登录支持...
  14. 合上电脑盖时,电脑断网-原因及解决方法
  15. 功率曲线k值_一种基于DTW的改进K-means的日负荷曲线聚类方法技术
  16. Android开发提供两个图片和视频的测试url
  17. java stream转byte[ ]
  18. matlab位移反分析公式,位移反分析.doc
  19. 非常实用的,国内十大另类行业网址导航站
  20. 《腾讯网UED体验设计之旅》

热门文章

  1. [转载]Android开发常用调试技术记录
  2. 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting
  3. [RN] React Native 自定义 底部 弹出 选择框 实现
  4. (27) java web的struts2框架的使用-基于表单的多文件上传
  5. ECMAScript 6 一些有意思的特性
  6. bzoj 4260: Codechef REBXOR
  7. JavaWeb实现文件上传下载功能实例解析
  8. node.js+express,实现RESTful API
  9. 用Javascript模拟微信飞机大战游戏
  10. Android开发之浅谈Service的基本概况和常见问题