首页 > 解决方案 > addEventListener 和 removeEventListener 在 Firefox/Chrome 与 Edge 中的不同行为

问题描述

与 Chrome 和 Firefox 相比,我最近在 Edge 执行一段 Javascript 的方式上遇到了一个奇怪的不一致。

当附加一个点击处理程序(错误的,意外)时,Edge 的反应如预期的那样。但是 Chrome 和 Firefox 忽略了错误的点击处理程序,隐藏了我的错误。

button.addEventListener("click", functionOne);

function functionOne(e) {
  console.log('functionOne called');
  functionTwo(e);
}

function functionTwo(e) {
  console.log('functionTwo called');
  
  // My intial mistake was here: According to my application logic, 
  // I should have removed the event listener for functionOne. Whoops.
  button.removeEventListener("click", functionThree);
  
  console.log("Doing some asynchronous work...");
  
  // Same here: I should have re-added the event listener for functionOne
  button.addEventListener("click", functionThree);
}

// This function is never called by FF and Chrome, but it is called in Edge
function functionThree(e) {
  console.error('functionThree called');
}

我打算在functionOne做一些异步工作时删除事件侦听器,然后在异步调用完成后重新连接。我的错误是removeEventListener()引用错误的函数 ( functionThree) 进行调用,然后附加另一个事件侦听器,该侦听button器也调用functionThree.

但奇怪的是,该代码在 Chrome 和 Firefox 中按预期工作。只有当我在 Edge 中尝试它时,我才注意到 Edge 正在调用functionThree,而 Chrome 和 Firefox 都忽略了它。

有人可以解释这种行为吗?为什么 Chrome 和 Firefox 不调用,functionThree虽然我附加了一个事件监听器?为什么Edge 这么称呼它

浏览器版本:

 FireFox  59.0.2
 Edge     41.16299.371.0 
 Chrome   66.0.3359.139

TL;DR - Firefox/Chrome 没有像我预期的那样附加事件侦听器。边缘做到了。

链接到 jsbin 示例

标签: javascriptgoogle-chromedom-eventsmicrosoft-edgeaddeventlistener

解决方案


根据我的观察,差异源于以下事实:

  • 在 chrome/firefox 和 IE 中,添加的 eventListener 不会为当前事件触发,而是为下一个事件触发。
  • 在 chrome/firefox 中删除的事件监听器立即阻止调用处理程序 WHEREAS 中,已经附加到元素上的处理程序将触发,但效果removeEventListener将在引擎的下一个滴答声中发生。

这就是为什么在这两种情况下(ie 和 firefox/chrome),第一次点击不会触发 function-3,但随后的点击将在 ie 中触发。为了纠正这种行为,我的解决方案是添加到 ie stopImmediatePropagation

function functionTwo(e) {

  console.log('functionTwo called');

  // My intial mistake was here: I put functionThree in by accident
  // and only then noticed the strange behaviour
  button.removeEventListener("click", functionThree);

  console.log("Doing some asynchronous work...");

  // Same here: I should have put functionOne as the second argument
  button.addEventListener("click", functionThree);
  e.stopImmediatePropagation();
}

现在 ie 将表现得像 firefox/chrome。


推荐阅读