【原】JS事件---冒泡与捕获相关的记录(一)

先上一张图来描述下冒泡与捕获~~

上图描述了两个div,div1及其子节点div2。我把冒泡理解为当触发div2的点击事件时,程序默认也会触发div1的点击事件,但事件触发的开始点是在最内部的节点,是由内而外的顺序(如上图向上箭头);捕获的概念刚好和冒泡相反。当你点击内部div2时,事件触发的开始点是最外部的节点,是由外而内的顺序(如上图向下箭头);

关于阻止冒泡网上有很多方法,大部分是建议ie下阻止冒泡用cancelBubble,标准下用stopPropagation,因为ie低版本不兼容stopPropagation,奇怪的是经测试发现cancelBubble在IE各个版本和标准下都兼容。此处贴两段测试代码。

    <div id="div1">
       div1
       <div id="div2">div2</div>
    </div>
     var oDiv1 = document.getElementById("div1");
     var oDiv2 = document.getElementById("div2");
     oDiv1.onclick = function(ev){
        alert(this.innerHTML);
     }
     oDiv2.onclick = function(ev){
        alert(this.innerHTML);
     }

---><--- 点击div2后,先触发div2的事件,后触发了div1的事件

     oDiv1.onclick = function(ev){
             alert(this.innerHTML);
     }
     oDiv2.onclick = function(ev){
             oEv = ev || window.event;
             //oEv.stopPropagation(); //阻止冒泡(ff,chrome,ie高版本都可以阻止冒泡)
             oEv.cancelBubble = true; //阻止冒泡(全兼容)
             alert(this.innerHTML);
     }

---><--- 点击div2后,只触发div2的事件

经过两段代码的对比测试发现,cancelBubble确实是全部兼容。cancelBubble字面意思是阻止泡沫,stopPropagation字面意思是阻止传播,貌似cancelBubble是特定用来阻止冒泡的。下面再测试下捕获的情况。IE低版本不支持捕获机制,且事件绑定方式需要用attachEvent做兼容,这里就不展开了,直接用addEventListener绑定事件。

     function fn1(){
         alert(this.innerHTML);
     }
     oDiv1.addEventListener("click",fn1,true);//第三个参数默认为false(冒泡模式),true为捕获模式
     oDiv2.onclick = function(ev){
             oEv = ev || window.event;
             //oEv.stopPropagation(); //阻止冒泡(ff,chrome,ie高版本都可以阻止冒泡)
             oEv.cancelBubble = true; //阻止冒泡(全兼容)
             alert(this.innerHTML);
     }

---><--- 捕获模式下,点击div2,先触发div1的事件,后触发div2的事件

     function fn1(ev){
         oEv = ev || window.event;
         oEv.cancelBubble = true; //尝试阻止捕获,chrome和ie高版本下不能阻止捕获,ff可以
         alert(this.innerHTML);
     }
     oDiv1.addEventListener("click",fn1,true);//第三个参数默认为false(冒泡模式),true为捕获模式
     oDiv2.onclick = function(ev){
             oEv = ev || window.event;
             //oEv.stopPropagation(); //阻止冒泡(ff,chrome,ie高版本都可以阻止冒泡)
             oEv.cancelBubble = true; //阻止冒泡(全兼容)
             alert(this.innerHTML);
     }

---><--- cancelBubble只在ff中可以阻止捕获,即点击div2后只触发了div1的事件。

     function fn1(ev){
         oEv = ev || window.event;
         //oEv.cancelBubble = true; //尝试阻止捕获,chrome和ie高版本下不能阻止捕获,ff可以
         oEv.stopPropagation(); //尝试阻止捕获,ff,chrome,ie高版本都可以阻止捕获
         alert(this.innerHTML);
     }
     oDiv1.addEventListener("click",fn1,true);//第三个参数默认为false(冒泡模式),true为捕获模式
     oDiv2.onclick = function(ev){
             oEv = ev || window.event;
             //oEv.stopPropagation(); //阻止冒泡(ff,chrome,ie高版本都可以阻止冒泡)
             oEv.cancelBubble = true; //阻止冒泡(全兼容)
             alert(this.innerHTML);
     }

---><--- 点击div2后只触发了div1的事件 (ff,chrome,ie高版本都可以阻止捕获)

上面的测试结果有点晕,我整理下。

一、在冒泡的情况下:

1.用cancelBubble阻止冒泡时,ff,chrome,ie各版本都可以阻止冒泡

2.用stopPropagation阻止冒泡时,ff,chrome,ie高版本可以阻止冒泡

二、在捕获的情况下:

1.用cancelBubble阻止捕获时,chrome和ie高版本下不能阻止捕获,ff可以 ( IE6,7,8不行,不支持捕获功能 )

2.用stopPropagation阻止捕获时,ff,chrome,ie高版本都可以阻止捕获 ( IE6,7,8不行,不支持捕获功能 )


这兼容性实在让人看不懂...我只能自己脑补下原因了:

早期ff和ie都支持cancelBubble阻止冒泡这种情况。但ff比ie要先进点,它还支持了用cancelBubble阻止捕获的情况,后来ff觉得不管是冒泡还是捕获模式,都可以理解为传播。因此ff引入了关键词stopPropagation来同时阻止冒泡和捕获,而且保留了cancelBubble也能同时阻止冒泡和捕获的功能。

与此同时IE经过发展,到了IE9版本时也支持了ff的那套stopPropagation阻止冒泡和捕获的功能,但IE觉得没有必要将ff保留的cancelBubble阻止捕获的功能也实现,毕竟那只是ff遗留下的功能。至于chrome,它更接近ff,但chrome可能早期并没有用cancelBubble实现过捕获功能,因此它在捕获上和IE一样,摒弃了ff遗留下的功能。

兼容的趋势应该是冒泡和捕获都被传播所替代了,传播既能阻止从外而内的,也能阻止从内而外的。至此我终于貌似可能好像有点不晕了。。。以上观点为个人观点和个人脑补的记录方式,欢迎交流指正 : )

 欢迎转载:转载时请注明本文出处及文章链接

标签:


添加新评论

captcha
请输入验证码