JS中的事件冒泡与捕获

刚接触 JS 的那个时候,啥也不懂,只想着如何利用 Google、百度到的函数来解决实际的问题,不会想到去一探究竟。

成都创新互联是创新、创意、研发型一体的综合型网站建设公司,自成立以来公司不断探索创新,始终坚持为客户提供满意周到的服务,在本地打下了良好的口碑,在过去的十多年时间我们累计服务了上千家以及全国政企客户,如墙体彩绘等企业单位,完善的项目管理流程,严格把控项目进度与质量监控加上过硬的技术实力获得客户的一致表扬。

渐渐的,对 JS 的语言的不断深入,有机会去了解一些原理性东西。最近在看 JQuery 源码,感触很多,总想着用原生的 JS 去实现自己的一个 JQuery 库。说实在的,JQuery 里面很多函数和思路,是千百开源工作者长期的贡献,哪能是短时间就能消化的了。

最近再次碰到 addEventListener函数(MDN 上关于 addEventListener 的介绍,很详细),由于之前并没有弄懂第三个参数的含义,要么默认值,要么手动设置成 false。这次看了不少文章,彻底把事件冒泡和捕获弄懂。

什么事件冒泡与捕获

事件冒泡与捕获是 DOM 中事件传播的两种方式,比如说对于注册了相同事件的两个 DOM 元素(简单点就是两个 div,一里一外),当点击里层 div 的时候,这两个事件谁先执行。

冒泡事件,由里向外,最里层的元素先执行,然后冒泡到外层。

捕获事件,由外向里,最外层的元素先执行,然后传递到内部。

在 IE 9 之前是只支持事件冒泡,IE 9(包括 IE 9) 之后和目前主流的浏览器都同时支持两种事件。

如何设置,只需修改 addEventListener的第三个参数,true 为捕获,false 为冒泡,默认为冒泡。

举个简单的例子,

 
 
  1.  
  2.    
  3.      
  4.    
 
  •  
  •   var dom_out = document.getElementsByClassName('out')[0]; 
  •   var dom_in = document.getElementsByClassName('in')[0]; 
  •   dom_out.addEventListener('click',function(){ 
  •     alert('out'); 
  •   },false); 
  •   dom_in.addEventListener('click',function(){ 
  •     alert('in'); 
  •   },false); 
  •  
  •  在上面这个例子中,事件是按照冒泡来执行的,点击里层的 in,会看到先 alert 的顺序是先 "in" 后 "out",如果把事件改成捕获,alert 的顺序又不一样了。

     
     
    1.  
    2.   var dom_out = document.getElementsByClassName('out')[0]; 
    3.   var dom_in = document.getElementsByClassName('in')[0]; 
    4.   dom_out.addEventListener('click',function(){ 
    5.     alert('out'); 
    6.   },true); 
    7.   dom_in.addEventListener('click',function(){ 
    8.     alert('in'); 
    9.   },true); 
    10.  

    上面这个例子是捕获事件的例子,点击 in效果是不是不一样呢?

    之所以会有冒泡和捕获事件(像 IE 9 之前的浏览器不支持捕获事件,还真是反程序员),毕竟在实际中处理事情肯定有个先后顺序,要么由里向外,要么由外向里,两者都是必须的。

    但有时候为了兼容 IE 9 以下版本的浏览器,都会把第三个参数设置成 false 或者默认(默认就是 false)。

    进一步理解冒泡和捕获

    现在已经说清楚冒泡和捕获,那么如果同时出现冒泡和捕获会出现什么结果?

    原来浏览器处理时间分为两个阶段,捕获阶段和冒泡阶段,

    来看一看例子就知道了:

     
     
    1.  
    2.   s1 
    3.     s2 
    4.       s3 
    5.        
    6.      
    7.    
      

    这次我们设置三个 span,分别是 s1, s2, s3,然后设置 s1,s3 为冒泡执行,s2 为捕获执行:

     
     
    1.  
    2.   var s1 = document.getElementsByClassName('s1')[0]; 
    3.   var s2 = document.getElementsByClassName('s2')[0]; 
    4.   var s3 = document.getElementsByClassName('s3')[0]; 
    5.   s1.addEventListener('click',function(){ 
    6.     alert('s1'); 
    7.   },false); 
    8.   s2.addEventListener('click',function(){ 
    9.     alert('s2'); 
    10.   },true); 
    11.   s3.addEventListener('click',function(){ 
    12.     alert('s3'); 
    13.   },false); 
    14.  

    从运行的效果来看,点击 s3,依次 alert s2 => s3 => s1,说明:

    默认事件取消与停止冒泡

    当然,有时候我们只想执行最内层或最外层的事件,根据内外层关系来把范围更广的事件取消掉(对于新手来说,不取消冒泡,很容易中招的出现 bug)。event.stopPropagation()(IE 中window.event.cancelBubble = true)可以用来取消事件冒泡。

    有时候对于浏览器的默认事件也需要取消,这时候用到的函数则是 event.preventDefault()(IE 中window.event.returnValue = false)。

    那么默认事件取消和停止冒泡有什么区别呢?我的理解:浏览器的默认事件是指浏览器自己的事件(这不废话吗),比如 a 标签 的点击,表单的提交等,取消掉就不会执行啦;冒泡则取消的是由外向里(捕获)、由里向外(冒泡),stop 之后,就不会继续遍历了。stackoverflow 上的解答

    看下例子,依旧是上面那个例子,不过每个函数都加了 停止冒泡:

     
     
    1. s1.addEventListener('click',function(e){ 
    2.   e.stopPropagation(); 
    3.   alert('s1'); 
    4. },false); 
    5. s2.addEventListener('click',function(e){ 
    6.   e.stopPropagation(); 
    7.   alert('s2'); 
    8. },true); 
    9. s3.addEventListener('click',function(e){ 
    10.   e.stopPropagation(); 
    11.   alert('s3'); 
    12. },false);  

    点击的结果是:当点击 s2 或 s3 的时候,都会 alert s2,点击 s1,弹出 s1。因为事件被取消的缘故,点击 s3,执行 s2后就不会在向下执行了。

    在看一个 preventDefault 的例子。

     
     
    1.  
    2.   点我回主页 
     
  •  
  •   点我不回主页 
  •  
  •  
  •   var back = document.getElementsByClassName('back')[0]; 
  •   back.addEventListener('click', function(e){ 
  •     e.preventDefault(); 
  •   }); 
  •  
  • 第二个链接是不是回不了主页,因为浏览器的默认事件被取消了。


    以上所有例子请在非低版本 IE 浏览器的环境下浏览 O_o

    总结

    总结就补充两个兼容 IE 的函数吧:

     
     
    1. function stopBubble(e) { 
    2.   //如果提供了事件对象,则这是一个非IE浏览器 
    3.   if ( e && e.stopPropagation ) 
    4.       //因此它支持W3C的stopPropagation()方法 
    5.       e.stopPropagation(); 
    6.   else 
    7.       //否则,我们需要使用IE的方式来取消事件冒泡 
    8.       window.event.cancelBubble = true; 
    9. //阻止浏览器的默认行为 
    10. function stopDefault( e ) { 
    11.   //阻止默认浏览器动作(W3C) 
    12.   if ( e && e.preventDefault ) 
    13.       e.preventDefault(); 
    14.   //IE中阻止函数器默认动作的方式 
    15.   else 
    16.       window.event.returnValue = false; 
    17.   return false; 
    18. }  

    共勉!

    参考

    stackoverflow 什么是事件冒泡和捕捉

    stackoverflow stopPropagation 和 preventDefault 的区别

    MDN addEventListener

    javascript阻止事件冒泡和浏览器的默认行为

    网站题目:JS中的事件冒泡与捕获
    转载来于:http://www.mswzjz.cn/qtweb/news41/278291.html

    攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能

    贝锐智能技术为您推荐以下文章

    电子商务知识

    行业网站建设