本期,边肖将为您带来关于如何在JS中冒泡和捕捉事件的信息。文章内容丰富,从专业角度进行分析和描述。看完这篇文章,希望你能有所收获。
刚接触JS的时候,什么都不知道。我只是想如何利用谷歌和百度找到的功能解决实际问题,但我不想知道。
渐渐地,随着JS语言的深入,我有机会了解一些原理。最近在看JQuery源代码的时候,感触良多。我一直想用原生JS来实现我自己的JQuery库。说实话,JQuery中的很多功能和思想都是成千上万开源工作者的长期贡献,可以在短时间内消化。
最近又遇到了addEventListener函数(MDN中对addEventListener的介绍非常详细)。因为之前没有理解第三个参数的含义,所以要么设置为默认值,要么手动设置为false。这次看了很多文章,彻底明白了事件的泡沫和捕捉。
什么事件冒泡与捕获
事件冒泡和捕获是DOM中事件传播的两种方式。例如,对于用同一个事件注册的两个DOM元素(简单来说就是两个div,一个在内部,一个在外部),当单击内部div时,谁将首先执行这两个事件?
冒泡事件,从内到外,首先执行最里面的元素,然后冒泡到外层。
捕获事件时,从外到内,首先执行最外面的元素,然后传递到内部。
在IE 9之前,只支持事件冒泡。IE 9以后(包括IE 9)和目前主流浏览器都支持这两个事件。
如何设置,只需修改addEventListener的第三个参数,true为capture,false为冒泡,默认为冒泡。
举个简单的例子,
div span class=' out ' span class=' in '/span/span/div script type=' text/JavaScript ' vardom _ out=document . getelementsbyclassname(' out ')[0];vardom _ in=document . getelementsbyclassname(' in ')[0];DOM _ out . addeventlistener(' click '),function(){ alert(' out ');},false);dom_in.addEventListener('click ',function(){ alert(' in ');},false);/脚本
在上面的例子中,事件是根据冒泡执行的。在内层点击进去,你会看到预警的顺序是先‘进’再‘出’。如果您将事件更改为捕获,警报的顺序将再次不同。
script type=' text/JavaScript ' vardom _ out=document . getelementsbyclassname(' out ')[0];vardom _ in=document . getelementsbyclassname(' in ')[0];DOM _ out . addeventlistener(' click '),function(){ alert(' out ');},真);d
om_in.addEventListener('click',function(){ alert('in'); },true); </script>
上面这个例子是捕获事件的例子,点击 in效果是不是不一样呢?
之所以会有冒泡和捕获事件(像 IE 9 之前的浏览器不支持捕获事件,还真是反程序员),毕竟在实际中处理事情肯定有个先后顺序,要么由里向外,要么由外向里,两者都是必须的。
但有时候为了兼容 IE 9 以下版本的浏览器,都会把第三个参数设置成 false 或者默认(默认就是 false)。
进一步理解冒泡和捕获
现在已经说清楚冒泡和捕获,那么如果同时出现冒泡和捕获会出现什么结果?
原来浏览器处理时间分为两个阶段,捕获阶段和冒泡阶段,
-
先执行捕获阶段,如果事件是在捕获阶段执行的(true 情况),则执行;
-
然后是冒泡阶段,如果事件是在冒泡阶段执行的(false 情况),则执行;
来看一看例子就知道了:
<div> <span class="s1">s1 <span class="s2">s2 <span class="s3">s3 </span> </span> </span> </div>
这次我们设置三个 span,分别是 s1, s2, s3,然后设置 s1,s3 为冒泡执行,s2 为捕获执行:
<script type="text/javascript"> var s1 = document.getElementsByClassName('s1')[0]; var s2 = document.getElementsByClassName('s2')[0]; var s3 = document.getElementsByClassName('s3')[0]; s1.addEventListener('click',function(){ alert('s1'); },false); s2.addEventListener('click',function(){ alert('s2'); },true); s3.addEventListener('click',function(){ alert('s3'); },false); </script>
从运行的效果来看,点击 s3,依次 alert s2 => s3 => s1,说明:
-
捕获事件和冒泡事件同时存在的,而且捕获事件先执行,冒泡事件后执行;
-
如果元素存在事件且事件的执行时间与当前逻辑一致(冒泡或捕获),则执行。
默认事件取消与停止冒泡
当然,有时候我们只想执行最内层或最外层的事件,根据内外层关系来把范围更广的事件取消掉(对于新手来说,不取消冒泡,很容易中招的出现 bug)。event.stopPropagation()(IE 中window.event.cancelBubble = true)可以用来取消事件冒泡。
有时候对于浏览器的默认事件也需要取消,这时候用到的函数则是 event.preventDefault()(IE 中window.event.returnValue = false)。
那么默认事件取消和停止冒泡有什么区别呢?我的理解:浏览器的默认事件是指浏览器自己的事件(这不废话吗),比如 a 标签 的点击,表单的提交等,取消掉就不会执行啦;冒泡则取消的是由外向里(捕获)、由里向外(冒泡),stop 之后,就不会继续遍历了。stackoverflow 上的解答
看下例子,依旧是上面那个例子,不过每个函数都加了 停止冒泡:
s1.addEventListener('click',function(e){ e.stopPropagation(); alert('s1'); },false); s2.addEventListener('click',function(e){ e.stopPropagation(); alert('s2'); },true); s3.addEventListener('click',function(e){ e.stopPropagation(); alert('s3'); },false);
点击的结果是:当点击 s2 或 s3 的时候,都会 alert s2,点击 s1,弹出 s1。因为事件被取消的缘故,点击 s3,执行 s2后就不会在向下执行了。
在看一个 preventDefault 的例子。
<div> <a href="/">点我回主页</a> </div> <div> <a href="/" class="back">点我不回主页</a> </div> <script type="text/javascript"> var back = document.getElementsByClassName('back')[0]; back.addEventListener('click', function(e){ e.preventDefault(); }); </script>
第二个链接是不是回不了主页,因为浏览器的默认事件被取消了。
总结就补充两个兼容 IE 的函数吧:
function stopBubble(e) { //如果提供了事件对象,则这是一个非IE浏览器 if ( e && e.stopPropagation ) //因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else //否则,我们需要使用IE的方式来取消事件冒泡 window.event.cancelBubble = true; } //阻止浏览器的默认行为 function stopDefault( e ) { //阻止默认浏览器动作(W3C) if ( e && e.preventDefault ) e.preventDefault(); //IE中阻止函数器默认动作的方式 else window.event.returnValue = false; return false; }
上述就是小编为大家分享的如何进行JS中的事件冒泡与捕获了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/97018.html