当你在浏览器上点击一个按钮时,点击的事件不仅仅发生在按钮上,同时点击的还有这个按钮的容器元素,甚至也点击了整个页面。

事件流  

  事件流描述了从页面接收事件的顺序,但在浏览器发展到第四代时,浏览器开发团队提出了两种完全相反的事件流。

  冒泡事件流:IE提出的事件流,即事件由最具体的元素接收,逐级向上,传播到页面。

  

  捕获事件流:Netscape提出的事件流,即事件由页面元素接收,逐级向下,传播到最具体的元素。

  

  两种事件流在DOM2级事件模型中得到了统一,相较于DOM0级事件模型,DOM2级有着如下特点:

    1、允许在某个元素上绑定多个同类型的事件

    2、规定了事件流的三个阶段:捕获阶段、目标阶段、冒泡阶段

    【测试】使用addEventListener输出事件流过程:

    分别在window、document、html、body、btn上绑定事件,单击按钮,输出结果如下[FF测试]

    

    可以看到当事件处于目标阶段时,并不只触发一次,而是分别属于捕获和冒泡两个阶段。

  尽管DOM2级事件规定了事件的三个阶段,但遗憾的是,IE8及以下浏览器只支持冒泡事件流。

    【测试】使用attachEvent输出事件流过程:

    分别在window、document、html、body、btn上绑定事件,单击按钮,输出结果如下[IE8测试]   

    

    可以看到仅输出了目标和冒泡阶段的信息,并且绑定在window上的事件并没有被触发,IE8及以下浏览器的冒泡事件仅冒泡到document

  目前支持以addEventListener绑定事件的浏览器:FF、Chrome、Safari、Opera、IE9-11

  目前支持以attachEvent绑定事件的浏览器:IE6-10

  测试浏览器支持情况,参考博客:[JS学习笔记]浅谈Javascript事件模型

阻止事件传递

  通过前面的讲述,可以知道在事件流中,某元素的事件被触发,同时也会导致其容器元素上的同类型事件被触发。但很多时候,我们并不希望这样的结果。

  此时可以通过stopPropagation()或cancelBubble来阻止事件向下一级元素传递。

stopPropagation()

  stopPropagation()是W3C标准下阻止事件传递的方法

  【测试】使用addEventListener绑定,测试stopPropagation():

  分别在box0-2上绑定事件,单击box0,输出结果[FF测试]

  由于addEventListener可以设置是否在捕获阶段运行,故可分为[在捕获阶段阻止事件传递]和[在冒泡阶段阻止事件传递] 

  1、在捕获阶段阻止事件传递

  

  

  2、在冒泡阶段阻止事件传递

  

  

  通过测试,可以看到当阻止事件传递后,事件流将不会继续执行。

  【测试】使用attachEvent绑定,测试stopPropagation():

  分别在box0-2上绑定事件,单击box0,输出结果[IE8测试]

  由于attachEvent不支持捕获事件流,故仅冒泡阶段测试其对stopPropagation()的支持程度:

  

  可以看到attachEvent的event对象不支持stopPropagation()方法

cancelBubble

  cancelBubble是IE标准下阻止事件传递的属性,设置cancelBubble=true表示阻止冒泡

  【测试】使用addEventListener绑定,测试cancelBubble:

  分别在box0-2上绑定事件,单击box0,输出结果

  1、在捕获阶段阻止:

  

  [FF测试]

  

  [Chrome测试]

  

  [IE11测试]

  

  可以看到,只有在FF上的结果是我们期望的结果,此外,通过对Safari、Opera进行测试,输出结果与Chrome一致;对IE9-10进行测试,输出结果与IE11一致

  2、在冒泡阶段阻止:

  

  

  FF、Chrome、Safari、Opera、IE9-11均输出上图结果。

  【测试】使用attachEvent绑定,测试cancelBubble:

  分别在box0-2上绑定事件,单击box0,输出结果[IE8测试]

  

  

总结

  综合测试结果,总结stopPropagation()及cancelBubble兼容性如下:

  element.on[type] = triggerFn addEventListener attachEvent
在冒泡阶段阻止 在捕获阶段阻止 在冒泡阶段阻止 在冒泡阶段阻止
stopPropagation() 除IE8及以下,其他均支持,且结果正确 支持,且结果正确 支持,且结果正确 不支持
cancelBubble 支持,且结果正确 支持,但只有FF正确 支持,且结果正确 支持,且结果正确

  使用时需要注意以下几点:

  1、虽然阻止事件传递分为W3C标准(stopPropagation())和IE标准(cancelBubble),但并不意味着该属性或方法为各自浏览器所所独有。测试表明,FF、Chrome等高级浏览器同样支持IE标准下的cancelBubble。

  2、若需要在捕获阶段阻止事件传递,使用addEventListener()进行事件监听,同时使用e.stopPropagation()阻止冒泡。

  3、若需要在冒泡阶段阻止事件传递,在兼容addEventListener()和attachEvent()的同时,为保险起见,需要对阻止事件传递方式进行兼容。以下仅表示在DOM2及事件模型下兼容方式:

  

阻止默认事件

  一些元素在一般状态下存在默认行为,如:

  对配置了href的<a>绑定单击事件fn1,点击后会首先执行fn1,但之后也会执行<a>标签的默认行为,即:跳转href指向的页面。

  对<form>中的<input type="submit">绑定单击事件fn2,点击后首先会执行fn2,之后再执行<input type="submit">的默认行为,即:提交表单数据。

  为解决元素默认事件对绑定事件的影响,我们可以采用event对象提供的方法进行处理。

preventDefault()

  preventDefault()是W3C标准下阻止元素默认事件的方法。

  【测试】使用DOM0事件模型进行绑定,测试preventDefault():

  在<a htrf = "http://www.baidu.com">上绑定单击事件,点击<a>,输出结果[FF]:

  

  

  点击链接后,输出“点击了<a>”,且页面不进行跳转,说明阻止事件成功。

  测试兼容性后发现,仅IE8及以下浏览器不支持preventDetault()

  

  【测试】使用DOM2事件模型addEventListener进行绑定,测试preventDefault():

  在<a htrf = "http://www.baidu.com">上绑定单击事件,点击<a>,输出结果[FF]:

  

  测试发现,对于支持addEventListener的浏览器,无论捕获还是冒泡阶段都可以阻止默认事件。

  【测试】使用DOM2事件模型attachEvent进行绑定,测试preventDefault():

  在<a htrf = "http://www.baidu.com">上绑定单击事件,点击<a>,输出结果[IE8]:

  

  测试发现,对于支持attachEvent的浏览器,均不支持e.preventDefault()

returnValue = false

  returnValue是IE标准下阻止元素默认事件的方法,设置returnValue = false表示阻止默认事件。

  【测试】使用DOM0事件模型进行绑定,测试returnValue:

  在<a htrf = "http://www.baidu.com">上绑定单击事件,点击<a>,输出结果[FF]:

  

  

  点击链接后,输出“点击了<a>”,但页面进行跳转,说明阻止事件失败。

  测试兼容性后发现,IE8、Chrome、Safari、Opera设置returnValue=false时,会阻止元素的默认事件;而FF、IE9-11则不会阻止。

  

  【测试】使用DOM2事件模型addEventListener进行绑定,测试returnValue:

  在<a htrf = "http://www.baidu.com">上绑定单击事件,点击<a>,输出结果[FF]:

  

  测试发现,对于支持addEventListener的浏览器:

  在捕获阶段:FF、IE9-11不会阻止默认事件,而Chrome、Opera、Safari会阻止。

  在冒泡阶段:IE9-11不会阻止默认事件,而FF、Chrome、Opear、Safari会阻止。

  【测试】使用DOM2事件模型attachEvent进行绑定,测试returnValue:

  在<a htrf = "http://www.baidu.com">上绑定单击事件,点击<a>,输出结果[IE8]:

  

  测试发现,对于支持attachEvent的浏览器,returnVaule=false可以阻止默认事件。

总结

  综合测试结果,preventDefault和returnValue的兼容性如下(T:支持该属性或事件且结果正确;F:不支持该属性或事件或结果不正确:—:不支持该事件绑定方式):

函数名 事件绑定方式 事件流 FF Chrome Opera Safari 模拟IE8 模拟IE9 模拟IE10 IE11
preventDetault() element.on[type] = fn 冒泡 T T T T F T T T
addEventListener() 捕获 T T T T T T T
冒泡 T T T T T T T
attachEvent() 冒泡 F F F
returnValue=false element.on[type] = fn 冒泡 F T T T T F F F
addEventListener() 捕获 F T T T F F F
冒泡 F T T T F F F
attachEvent() 冒泡 T F F

  使用时需要注意以下几点:

  1、为兼容不同浏览器,可编写如下代码:

  

  但实际上,这样也存在着雷区,对于IE9和IE10,支持addEventListener和attachEvent进行事件绑定,而对照上表,IE9和IE10在使用attachEvent进行绑定时,无法阻止默认事件。故应在事件绑定兼容时,优先检验addEventListener。

  2、以前一直将returnValue = false与return false混淆,此处应注意returnValue是IE标准下Event对象的属性,仅用于阻止元素的默认事件。而return false的作用范围更加广泛,如:阻止事件、跳出循环、返回对象等等,方便的一刀切容易出错,不可滥用。

[JS学习笔记]Javascript事件阶段:捕获、目标、冒泡的更多相关文章

  1. 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果

    学习笔记---Javascript事件Event.IE浏览器下的拖拽效果     1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...

  2. JS学习笔记6_事件

    1.事件冒泡 由内而外的事件传播(从屏幕里飞出来一支箭的感觉) 2.事件捕获 由表及里的事件传播(力透纸背的感觉) 3.DOM事件流(DOM2级) 事件捕获阶段 -> 处于目标阶段 -> ...

  3. [前端JS学习笔记]JavaScript CallBack

    一.概念介绍 CallBack : "回调" . 在spring优秀框架回调无处不在, 回调的运用场景很多, 如 swt事件监听.netty等.它的主要作用是提高程序执行效率, 一 ...

  4. [前端JS学习笔记]JavaScript function

    一.函数的声明 1.1 function 命令 function methodName(params) { // code } 如下声明: function test_function(params) ...

  5. js学习笔记----JavaScript中DOM扩展的那些事

    什么都不说,先上总结的图~   Selectors API(选择符API) querySelector()方法 接收一个css选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null ...

  6. [前端JS学习笔记]JavaScript prototype 对象

    一.概念介绍 prototype 对象 : 原型对象.在JavaScript中, 每一个对象都继承了另一个对象,后者称为"原型对象". 只有 null 除外,它没有自己的原型对象. ...

  7. [前端JS学习笔记]JavaScript 数组

    一.JavaScript数组的奇葩 大多数语言会要求数组的元素是同个类型, 但是JavaScript允许数组元素为多种类型. var arr = ["羽毛球", 666, {&qu ...

  8. JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)

    JavaScript继承的6种方法 1,原型链继承 2,借用构造函数继承 3,组合继承(原型+借用构造) 4,原型式继承 5,寄生式继承 6,寄生组合式继承 1.原型链继承. <script t ...

  9. JS学习笔记5_DOM

    1.DOM节点的常用属性(所有节点都支持) nodeType:元素1,属性2,文本3 nodeName:元素标签名的大写形式 nodeValue:元素节点为null,文本节点为文本内容,属性节点为属性 ...

随机推荐

  1. [设计模式]State模式

    <Java与模式> 又称状态对象模式.状态模式是对象的行为模式.GOF95 一个对象的行为取决于一个或者多个动态变化的属性,这样的属性叫做状态.这样的对象叫做有状态的对象(stateful ...

  2. Appium做Android功能自动化测试

    前言 做Android端功能自动化已有2年多的时间了,使用过的功能自动化框架有Robotium.Uiautomator.Appium.最近研究自动化case复用的方案,调研了Appium的自动化框架, ...

  3. Codeforces Round #302 (Div. 2)

    A. Set of Strings 题意:能否把一个字符串划分为n段,且每段第一个字母都不相同? 思路:判断字符串中出现的字符种数,然后划分即可. #include<iostream> # ...

  4. 微信小程序学习笔记(7)--------布局基础

    ui布局基础 一.flex布局 1.flex的容器和元素 2.flex容器属性详解     1>flex-direction不仅设置元素的排列方向,还设置主轴和交叉轴如下图主轴是由上到下 2&g ...

  5. Python框架之Tornado(请求阶段)

    上图是tornado程序启动以及接收到客户端请求后的整个过程,对于整个过程可以分为两大部分: 启动程序阶段,又称为待请求阶段(上图1.2所有系列和3.0) 接收并处理客户端请求阶段(上图3系列) 简而 ...

  6. HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】

    HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...

  7. 增for语句内容

    #author:leon #"hello world!" for i in range(10): #循环十次,每一次循环赋一个0-9中的数字给i . print("--- ...

  8. SVN如何切换用户对代码进行操作

    在使用svn更新或提交数据时需要输入用户名和密码,在输入框中可以选择是否记录,以便下次操作无需再次输入用户名和密码: 要切换其他用户名时,需要删除已记录用户的数据,在电脑桌面上右击,依次点击菜单项To ...

  9. Hadoop25---netty,单个handler

    ke客户端: package cn.itcast_03_netty.sendstring.client; import io.netty.bootstrap.Bootstrap; import io. ...

  10. VMWare 安装时报错 tools-windows.msi failed报错解决办法

    1.我用的是7.1.3版本的,到官方网站上下载这个版本的tools安装包 http://softwareupdate.vmware.com/cds/vmw-desktop/ws/7.1.3/32428 ...