Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

关于事件监听列表的操作细节

  标准的DOM操作接口中提供了addEventListener和removeEventListener方法来添加或移除事件,但是他们在规范里的定义并不太明确,而且在不同版本的规范中有不同的描述,所以从规范上来看我们无法确定浏览器实现这两个方法的具体行为。
  在事件处理过程中,对事件监听列表的操作有什么样的行为?或者说,事件触发时是先读取出整个事件监听列表还是从事件监听列表中逐个取出处理?就这个问题,我们看测试的结果。 <script>
addEventListener("click",function(e){
  console.log("init");
  removeEventListener("click",handle);
  addEventListener("click",function(){
    console.log("new");
  });
});
addEventListener("click",handle);
function handle(){
  console.log("old");
};
</script>

  这个测试在Chrome和Firefox上的结果是相同的,但是在IE上old也会被触发。也就是说,在事件触发过程中移除事件对于IE是不会造成影响的,但是事件确实被移除了。但是这个测试中也同时添加了新事件,而这个添加的新事件在所有浏览器中都不会被触发。对于IE的情况我们可以这么描述:“在IE(9-11)上,一个元素的事件开始触发时,先取出它的事件监听列表后再遍历,之后对事件监听列表的操作不会影响本次遍历。”。再看Chrome和Firefox的逻辑就有点诡异了,它们的处理并不针对事件监听列表,而是针对事件监听列表的操作方法,可以描述为:“在Chrome(31)和Firefox(25)上,一个元素的事件开始触发之后,添加到这个元素上的事件监听或从这个元素上移除的事件监听都不会在本次事件中被遍历到。”。
  这里,我一直在强调“一个元素”,因为事件监听列表是相对于元素的。一个事件触发可以影响到多个元素,这些元素是逐个被处理的,所以元素上的事件监听列表也是逐个被遍历的。因此在一次冒泡事件中对其父元素添加的事件也会被触发到。
<input type="button" id="btn" value="test" />
<script>
btn.addEventListener("click",function(e){
  //这个事件是添加到window上的所以可以被触发
  addEventListener("click",handle);
});
function handle(){
  console.log("handle");
};
</script>
  总之我觉得IE的逻辑比较清晰,jQuery的事件封装也是和IE的逻辑是一样的。
网名:
34.203.213.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^