【20190415】JavaScript-事件流与stopPropagation()、stopImmediatePropagation()的误区解析
这两天仔细看了一下MDN上关于事件流机制和相关方法的文档,发现有个很大的误区。过去我一直以为stopPropagation()就是用来阻止事件冒泡的,甚至很多博客和菜鸟教程上都是这样写的。但实际上文档中对stopPropagation()的解释是:
The
stopPropagation()method of theEventinterface prevents further propagation of the current event in the capturing and bubbling phases
阻止当前事件在捕获和冒泡阶段的进一步传播,我的理解就是阻止当前事件的继续传播,不仅阻止冒泡,也阻止捕获和目标阶段,只在于你是在哪个阶段调用stopPropagation()的。
事件流过程
一个事件被触发,它的事件流包括三个阶段:捕获、目标、冒泡。捕获阶段的传播路径是:window对象→document→HTML→body→...→target的直接父元素,从最外层最不具体的元素层层传递到最里层具体的元素。目标阶段就是事件目标元素上发生。冒泡阶段与捕获阶段的传播路径正好相反:target→...→body→HTML→document→window,一般会将目标阶段看作冒泡阶段的一部分。
事件的传播路径在事件开始传播之前就已经确定,如果在传播过程中DOM结构发生变化,那么也会按照根据原来的结构而生成的传播路径进行传播。
添加事件监听:addEventListener(eventType, function, useCapture)
useCapture为true,表示该监听器监听捕获阶段的事件,useCapture为false,则监听冒泡阶段的事件。如果是在事件目标元素上添加的事件监听,那么不管useCapture设置为true还是false都能监听到,而且此时的事件阶段eventPhase为2。
简单来说就是为某个元素添加一个事件监听器,当有事件传播到该元素时,如果事件处于捕获阶段,eventPhase=1,那么设置了useCapture为true的监听器就会响应。如果事件传播到该元素时处于冒泡阶段,eventPhase=3,那么设置了useCapture为false的监听器响应。如果事件传播到该元素时处于目标阶段,eventPhase=2,那么不管是设置了true还是false的监听器都能响应。
下面是个例子:
<div class="first">first
<div class="second">
<label>click me
<input type="checkbox" class="target">
</label>
</div>
</div>
<script>
let div1=document.getElementsByClassName('first')[0],
div2=document.getElementsByClassName('second')[0],
target=document.getElementsByClassName('target')[0];
div1.addEventListener('click',(e)=>{
alert('first: '+e.eventPhase+'1');
},true);
div1.addEventListener('click',(e)=>{
alert('first: '+e.eventPhase+'2');
},true);
div1.addEventListener('click',(e)=>{
alert('first: '+e.eventPhase);
},false); div2.addEventListener('click',(e)=>{
alert('second: '+e.eventPhase);
},true);
div2.addEventListener('click',(e)=>{
alert('second: '+e.eventPhase); },false);
target.addEventListener('click',(e)=>{
alert('target: '+e.eventPhase);
},true);
target.addEventListener('click',(e)=>{
alert('target: '+e.eventPhase);
},false);
</script>
点击CheckBox后,依次弹出“first:11”、“first:12”、“second:1”、“target:2”、“target:2”、“second:3”、“first:3”。
stopPropagation()
那么stopPropagation()方法就比较好理解了,如果在某个阶段在事件监听函数里调用了事件的stopPropagation()方法,那么该事件后续的传播过程都会被阻止,不论是捕获还是处于目标或者冒泡。
比如你在捕获阶段监听到事件,并且调用了stopPropagation()方法,那么后续的在子节点上的捕获过程(如果还有的话,如果是在捕获过程的最后一个节点上调用,那么就是直接阻止将要进行的目标过程)、处于目标过程、冒泡过程都会被阻止。如果在处于目标阶段调用,那么后续的冒泡过程被阻止。如果在冒泡过程调用,后续的在其他节点上的冒泡传播被阻止。
这里要注意的是,stopPropagation()是以元素节点间的传播为单位,如果后续的传播过程中事件需要从一个元素节点流转到它的父节点或子节点,那么stopPropagation()将会阻止这样的过程。也就是说在一个元素节点内,它是不起作用的,如果在调用stopPropagation()的元素节点内还存在其他事件监听,并且与调用stopPropagation()的监听器的响应规则是一样的,那么这些其他的监听依然会按顺序响应。
例如在上面的例子中,first有两个捕获阶段的事件监听器,在第一个里调用stopPropagation(),那么第二个监听依然会响应,但是后续的捕获、目标和冒泡过程都被阻止了。因此最终只会弹出first的两个弹窗:“first:11”、“first:12”;
stopImmediatePropagation()
而stopImmediatePropagation()在调用后就直接阻止事件的后续传播过程了,包括同一个元素节点内的过程。如果在调用stopImmediatePropagation()的元素节点上还有其他事件监听,那么在调用stopImmediatePropagation()后,其他事件监听也不会响应。
还是以上面的例子,如果在first的第一个捕获监听器里调用stopImmediatePropagation(),那么最终只会有一个弹窗:“first:11”。
如果在target的捕获监听器里调用stopImmediatePropagation(),弹窗结果是:“first:11”、“first:12”、“second:1”、“target:2”。
preventDefault()
很多人把preventDefault()和阻止冒泡、捕获搞混,实际上preventDefault()和事件传播过程没有关系,它的作用是阻止事件的默认行为,例如a标签在click事件后的默认行为是链接到新的页面,checkbox的click事件默认行为是将修改的选中状态生效。preventDefault()的作用则是阻止这些默认行为,它不会影响事件的传播,而且无论在事件的哪个阶段调用preventDefault(),都能阻止默认行为。
【20190415】JavaScript-事件流与stopPropagation()、stopImmediatePropagation()的误区解析的更多相关文章
- JavaScript事件流原理解析
一.为什么会有这一篇的文章 国庆前几天由于任务比较重,要赶在国庆前把一个进度的任务开发完成,所以也就有点赶,但是却遇到了一个比较奇怪的Bug,导致了任务比预计的延迟了几个小时,对此深表遗憾,所以利用国 ...
- 浅析JavaScript事件流——冒泡
一.什么是事件冒泡流 我们知道事件流指的是从页面中接受事件的顺序. 为了形象理解事件冒泡,可以想象三军主将诸葛亮,在帐内运筹帷幄,眼观六路耳听八方,这时候前方的战事情况就需要靠传令兵来传达,当第一位传 ...
- 【原】javascript事件流
摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原 ...
- 深入理解javascript事件流
摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原 ...
- 深入了解javascript事件流
摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原 ...
- javaScript事件流是什么?
一.事件 事件是文档或者浏览器窗口中发生的,特定的交互瞬间. 事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字. 事件是javaScript和DOM之间交 ...
- JavaScript事件流
什么是JS事件流 早期的IE事件传播方向为由上至下,即从document逐级向下传播到目标元素:而Netscape公司的Netscape Navigator则是朝相反的方向传播, 也就是从目标元素开始 ...
- javascript 事件流及应用
当页面元素触发事件的时候,该元素的容器以及整个页面都会按照特定顺序发生该元素的触发 事件,事件传播的顺序叫做事件流 1.事件流的分类: A.冒泡型事件(所有浏览器都支持) 由明确的事件源到最不确定 ...
- javascript事件流机制
(1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. IE 5.5: div -> body -> document IE 6.0: div ...
随机推荐
- 解决 spring-cloud-starter-zipkin 启动错误
应用场景:Spring Boot 服务添加 Zipkin 依赖,进行服务调用的数据采集,然后进行 Zipkin-Server 服务调用追踪显示. 示例pom.xml配置: <parent> ...
- 实现CSS隐藏滚动条并可以滚动内容
隐藏滚动条的同时还需要支持滚动,我们经常在前端开发中遇到这种情况,最容易想到的是加一个iscroll插件,但其实现在CSS也可以实现这个功能,我已经在很多地方使用了,下面一起看看这三种方法. 方法1: ...
- 安装与配置Flutter开发环境
这篇博客我们介绍了Flutter,并且对比了H5,React Native,Flutter. 由于Flutter是跨平台的开发框架,开发一次可以同时运行在Android和iOS上面,所以我们开发时最好 ...
- YOU种你来丨i春秋校园行第一站北京电子科技学院
发通告啦 i春秋互联网安全校园行即将火爆开启,第一站我们将来到北京电子科技学院.对网络安全感兴趣的大学生们注意啦,我们将走进校园送福利,Are you ready? i春秋简介 i春秋拥有全国最大的网 ...
- 美图App的移动端DNS优化实践:HTTPS请求耗时减小近半
本文引用了颜向群发表于高可用架构公众号上的文章<聊聊HTTPS环境DNS优化:美图App请求耗时节约近半案例>的部分内容,感谢原作者. 1.引言 移动互联网时代,APP 厂商之间的竞争非常 ...
- [Swift]LeetCode953. 验证外星语词典 | Verifying an Alien Dictionary
In an alien language, surprisingly they also use english lowercase letters, but possibly in a differ ...
- [Swift]LeetCode353. 设计贪吃蛇游戏 $ Design Snake Game
Design a Snake game that is played on a device with screen size = width x height. Play the game onli ...
- 《关于长沙.NET技术社区未来发展规划》问卷调查结果公布
那些开发者们对于社区的美好期待 2月,长沙.net 技术社区自从把群拉起来开始,做了一次比较正式.题目为<关于长沙.NET技术社区未来发展规划>的问卷调查,在问卷调查中,溪源写道: 随着互 ...
- Python内置函数(68)——__import__
英文文档: __import__(name, globals=None, locals=None, fromlist=(), level=0) This function is invoked by ...
- Qt之自定义检索框
1.效果展示 今天这篇文章主要讲解的是自定义搜索框,不仅仅支持搜索,而且可以支持搜索预览,具体请看效果图1.网上也有一些比较简单明了的自定义搜索框,比如Qt之自定义搜索框,讲的也比较详细,不过本文的侧 ...