刚接触JS的时候,什么都不懂。只想着如何利用谷歌和百度的功能来解决实际问题,并没有想到去了解。渐渐地,随着对JS语言的深入,我有机会了解一些基础的东西。最近一直在看JQuery的源码,感触颇多。一直想用原生的JS实现一个自己的JQuery库。说实话,JQuery中的很多功能和思想都是成千上万的开源工作者长期贡献的,不是短时间消化的。最近又遇到了addEventListener这个函数(MDN上addEventListener的介绍很详细)。由于之前不理解第三个参数的含义,所以要么设置默认值,要么手动设置为false。这次看了很多文章,把事件冒泡和捕获搞明白了。什么是事件冒泡和捕获事件冒泡和捕获是DOM中事件传播的两种方式。例如,对于注册了同一个事件的两个DOM元素(简单点就是两个div,一个在里面,一个在外面),当点击里面的图层div时,这两个事件先执行哪个。冒泡事件,从内到外,先执行最里面的元素,然后冒泡到外层。捕获事件,从外到内,最外层的元素先执行,再传递给里面。在IE9之前,只支持事件冒泡。IE9之后(包括IE9)和现在的主流浏览器,都同时支持这两个事件。如何设置,修改addEventListener的第三个参数即可,true为捕获,false为冒泡,默认为冒泡。举个简单的例子,
上面的例子中,事件是按照冒泡方式执行的,点击内层in,会看到第一个alert警报的顺序是先“入”后“出”。如果事件改为捕获,则警报的顺序不同。上面的例子是捕获事件的例子,点击in效果不一样?之所以会出现冒泡和捕获事件(像IE9之前的浏览器不支持捕获事件,真是反程序员),毕竟在实践中要处理的东西一定是序列化的,要么由内而外,或外在,两者都是必要的。但有时为了兼容IE9以下的浏览器,第三个参数会设置为false或default(默认为false)。进一步理解冒泡和捕获既然冒泡和捕获已经解释清楚了,那么如果冒泡和捕获同时发生会怎样呢?原来浏览器处理时间分为两个阶段,捕获阶段和冒泡阶段,捕获阶段先执行,如果事件在捕获阶段执行(truecase),则执行;然后是冒泡阶段,如果事件在冒泡阶段执行过(falsecase),则执行;我们来看例子:
s1s2s3
这次我们设置三个span,分别是s1,s2,s3,然后设置s1,s3为冒泡执行,s2为捕获执行:从运行效果来看,点击s3,然后alerts2=>s3=>s1,说明:捕获事件和冒泡事件同时存在,先执行捕获事件,后执行冒泡事件;如果元素中有事件且事件执行时间与当前逻辑(冒泡或捕获)一致,则执行。默认事件取消和冒泡停止当然有时候我们只想执行最内层或者最外层的事件,根据内外层的关系取消更大范围的事件(对于新手来说,不取消是很容易的冒泡有容易中招的bug)。event.stopPropagation()(window.event.cancelBubble=trueinIE)可以用来取消事件冒泡。有时浏览器的默认事件也需要取消,此时使用的函数是event.preventDefault()(IE中window.event.returnValue=false)。那么取消默认事件和停止冒泡有什么区别呢?我的理解:浏览器的默认事件是指浏览器自身的事件(这不是废话吗),比如a标签的点击,表单的提交等,取消了是不会执行的;从外到内(捕获)和从内到外(冒泡)取消冒泡。停止后不再继续遍历。看看stackoverflow上答案的例子,还是上面的例子,只是每个函数都加了stopbubbling: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时,会提醒s2,点击s1,s1会弹出。因为取消了事件,点击s3,执行完s2后,就不会再往下执行了。查看preventDefault的示例。
这两个链接无法返回首页,因为浏览器的默认事件已经取消。请在非低版本IE浏览器环境下浏览以上所有例子O_oSummaryandsummary添加两个兼容IE的函数:functionstopBubble(e){//如果提供了事件对象,那么这是非IE浏览器if(e&&e.stopPropagation)//所以支持W3C的stopPropagation()方法e.stopPropagation();else//否则需要用IE取消事件冒泡window.event.cancelBubble=true;}//屏蔽浏览器的默认behaviorfunctionsstopDefault(e){//防止浏览器默认动作(W3C)if(e&&e.preventDefault)e.preventDefault();//防止IE中函数设备默认动作的方式elsewindow.event.returnValue=false;returnfalse;}鼓励!参考stackoverflow什么是事件冒泡和捕获stackoverflowstopPropagationandpreventDefaultMDNaddEventListenerjavascript防止事件冒泡和浏览器默认行为