[解惑]JavaScript事件机制

群里童鞋问到关于事件传播的一个问题:“事件捕获的时候,阻止冒泡,事件到达目标之后,还会冒泡吗?”。

初学 JS 的童鞋经常会有诸多疑问,我在很多 QQ 群也混了好几年了,耳濡目染也也收获了不少,以后会总结下问题的结论,顺便说说相关知识的扩展~

如果贸然回答还会冒泡,这不太好的,稍微严谨点考虑 0级 DOM 事件模型的话,这个答案是否定的。但是在 2级 DOM 事件模型中,答案是肯定的,这个问题值得探讨记录下。

本文地址:http://www.cnblogs.com/hustskyking/p/problem-javascript-event.html 

一、问题结论

netscape 和 微软 曾经的战争还是比较火热的,当时, netscape 主张捕获方式,微软主张冒泡方式。后来 w3c 采用折中的方式,平息了战火,制定了统一的标准——先捕获再冒泡。

 事件的触发有三个阶段
  1. document 往事件触发地点,捕获前进,遇到相同注册事件立即触发执行
  2. 到达事件位置,触发事件
  3. 事件触发地点往 document 方向,冒泡前进,遇到相同注册事件立即触发

这么说很多人比较迷糊,我们在注册事件的时候,通常使用的是 捕获 或者 冒泡 的 一种:

obj.addEventListener("click", func, true); // 捕获方式
obj.addEventListener("click", func, false); // 冒泡方式

事件只会因为捕获或者冒泡触发一次。举个栗子:

点击 s2,结果是:

因为这里采用的是捕获模式,从 document 往 s2 走,依次发现 s1 和 s2 都有注册捕获事件,于是便触发了,然后冒泡,没找到冒泡事件,不执行任何操作。如果将 true 改成 false,可以看到结果相反。为了更好的让你理解整个事件机制,我给他们的捕获和冒泡模式下都注册事件:

结果真是太清晰了:

 

二、误区

指出两个误区。

1. 在同一个对象上注册事件,并不一定按照注册顺序执行

这一点,从上面的例子可以看出,你随便打乱四个事件绑定的顺序,结果依然不变!出现这样结果的原因是存在捕获模式和冒泡模式

2.event.stopPropagation();就是阻止事件的冒泡

这个表述不能说他错误,但是是不完整的,他除了阻止事件的冒泡,还阻止事件的继续捕获,简而言之就是组织事件的进一步传播。下面的例子可以看到:

结果是输出了 s1.

 

三、拓展

1. stopImmediatePropagation 的使用

这玩意儿是 w3c 的东西,使用的也不是特别的,我们知道 stopPropagation 可以阻止事件的进一步传播,但是他阻止不了该元素上绑定的其他函数的执行,比如我们在 obj 上绑定了 func1 和 func2,如果我们在 func1 中使用了 stopPropagation ,那 func2 依然还是会执行出来。倘若这里使用 stopImmediatePropagation,结果就不一样了,他不仅阻止事件的传播,还阻止 func2 的执行。如:

结果是:

而改成evt.stopImmediatePropagation();之后,阻止了第二个监听事件的触发:

结果是:

2. setCapture 和 releaseCapture

这两个是 IE 下的时间绑定函数,只要我们在某个元素上 setCapture 了,那么你在任何地方的鼠标操作(mouseXXX之类的动作)都会在这个元素上触发(前提是你在这个元素上绑定了事件),releaseCapture 或者本窗口失去聚焦才会释放这个绑定~

 

四、小结

对于此类知识的学习,应该查阅官方点的文档,或者看看《JavaScript权威指南》的解说,后期会经常整理诸如此类的问题。若有疑问,可以在下方评论中提出。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。