当你在浏览器上点击一个按钮时,点击的事件不只仅发生在按钮上,同时点击的还有这个按钮的容器元素,甚至也点击了整个页面。html
事件流描述了从页面接收事件的顺序,但在浏览器发展到第四代时,浏览器开发团队提出了两种彻底相反的事件流。浏览器
冒泡事件流:IE提出的事件流,即事件由最具体的元素接收,逐级向上,传播到页面。函数
捕获事件流:Netscape提出的事件流,即事件由页面元素接收,逐级向下,传播到最具体的元素。post
两种事件流在DOM2级事件模型中获得了统一,相较于DOM0级事件模型,DOM2级有着以下特色:学习
一、容许在某个元素上绑定多个同类型的事件测试
二、规定了事件流的三个阶段:捕获阶段、目标阶段、冒泡阶段url
【测试】使用addEventListener输出事件流过程:spa
分别在window、document、html、body、btn上绑定事件,单击按钮,输出结果以下[FF测试]orm
能够看到当事件处于目标阶段时,并不仅触发一次,而是分别属于捕获和冒泡两个阶段。htm
尽管DOM2级事件规定了事件的三个阶段,但遗憾的是,IE8及如下浏览器只支持冒泡事件流。
【测试】使用attachEvent输出事件流过程:
分别在window、document、html、body、btn上绑定事件,单击按钮,输出结果以下[IE8测试]
能够看到仅输出了目标和冒泡阶段的信息,而且绑定在window上的事件并无被触发,IE8及如下浏览器的冒泡事件仅冒泡到document
目前支持以attachEvent绑定事件的浏览器:IE6-10
经过前面的讲述,能够知道在事件流中,某元素的事件被触发,同时也会致使其容器元素上的同类型事件被触发。但不少时候,咱们并不但愿这样的结果。
此时能够经过stopPropagation()或cancelBubble来阻止事件向下一级元素传递。
stopPropagation()是W3C标准下阻止事件传递的方法
【测试】使用addEventListener绑定,测试stopPropagation():
分别在box0-2上绑定事件,单击box0,输出结果[FF测试]
因为addEventListener能够设置是否在捕获阶段运行,故可分为[在捕获阶段阻止事件传递]和[在冒泡阶段阻止事件传递]
一、在捕获阶段阻止事件传递
二、在冒泡阶段阻止事件传递
经过测试,能够看到当阻止事件传递后,事件流将不会继续执行。
【测试】使用attachEvent绑定,测试stopPropagation():
分别在box0-2上绑定事件,单击box0,输出结果[IE8测试]
因为attachEvent不支持捕获事件流,故仅冒泡阶段测试其对stopPropagation()的支持程度:
能够看到attachEvent的event对象不支持stopPropagation()方法
cancelBubble是IE标准下阻止事件传递的属性,设置cancelBubble=true表示阻止冒泡
【测试】使用addEventListener绑定,测试cancelBubble:
分别在box0-2上绑定事件,单击box0,输出结果
一、在捕获阶段阻止:
[FF测试]
[Chrome测试]
[IE11测试]
能够看到,只有在FF上的结果是咱们指望的结果,此外,经过对Safari、Opera进行测试,输出结果与Chrome一致;对IE9-10进行测试,输出结果与IE11一致
二、在冒泡阶段阻止:
FF、Chrome、Safari、Opera、IE9-11均输出上图结果。
【测试】使用attachEvent绑定,测试cancelBubble:
分别在box0-2上绑定事件,单击box0,输出结果[IE8测试]
综合测试结果,总结stopPropagation()及cancelBubble兼容性以下:
element.on[type] = triggerFn | addEventListener | attachEvent | ||
在冒泡阶段阻止 | 在捕获阶段阻止 | 在冒泡阶段阻止 | 在冒泡阶段阻止 | |
stopPropagation() | 除IE8及如下,其余均支持,且结果正确 | 支持,且结果正确 | 支持,且结果正确 | 不支持 |
cancelBubble | 支持,且结果正确 | 支持,但只有FF正确 | 支持,且结果正确 | 支持,且结果正确 |
使用时须要注意如下几点:
一、虽然阻止事件传递分为W3C标准(stopPropagation())和IE标准(cancelBubble),但并不意味着该属性或方法为各自浏览器所所独有。测试代表,FF、Chrome等高级浏览器一样支持IE标准下的cancelBubble。
二、若须要在捕获阶段阻止事件传递,使用addEventListener()进行事件监听,同时使用e.stopPropagation()阻止冒泡。
三、若须要在冒泡阶段阻止事件传递,在兼容addEventListener()和attachEvent()的同时,为保险起见,须要对阻止事件传递方式进行兼容。如下仅表示在DOM2及事件模型下兼容方式:
一些元素在通常状态下存在默认行为,如:
对配置了href的<a>绑定单击事件fn1,点击后会首先执行fn1,但以后也会执行<a>标签的默认行为,即:跳转href指向的页面。
对<form>中的<input type="submit">绑定单击事件fn2,点击后首先会执行fn2,以后再执行<input type="submit">的默认行为,即:提交表单数据。
为解决元素默认事件对绑定事件的影响,咱们能够采用event对象提供的方法进行处理。
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是IE标准下阻止元素默认事件的方法,设置returnValue = false表示阻止默认事件。
【测试】使用DOM0事件模型进行绑定,测试returnValue:
在<a htrf = "http://www.baidu.com">上绑定单击事件,点击<a>,输出结果[FF]:
点击连接后,输出“点击了<a>”,但页面进行跳转,说明阻止事件失败。
测试兼容性后发现,IE八、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 | — |
使用时须要注意如下几点:
一、为兼容不一样浏览器,可编写以下代码:
但实际上,这样也存在着雷区,对于IE9和IE10,支持addEventListener和attachEvent进行事件绑定,而对照上表,IE9和IE10在使用attachEvent进行绑定时,没法阻止默认事件。故应在事件绑定兼容时,优先检验addEventListener。
二、之前一直将returnValue = false与return false混淆,此处应注意returnValue是IE标准下Event对象的属性,仅用于阻止元素的默认事件。而return false的做用范围更加普遍,如:阻止事件、跳出循环、返回对象等等,方便的一刀切容易出错,不可滥用。