在FF / Chrome与Edge中的addEventListener和removeEventListener不同的行为

时间:2018-05-04 14:07:37

标签: javascript google-chrome javascript-events microsoft-edge addeventlistener

我最近遇到了与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?为什么 边缘调用它?

浏览器版本:

 FireFox  59.0.2
 Edge     41.16299.371.0 
 Chrome   66.0.3359.139

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

Link to jsbin example

1 个答案:

答案 0 :(得分:0)

根据我的观察,差异源于这样一个事实:

  • 在两个chrome / firefox中,即添加的eventListener不会为当前事件触发,而是下一个事件。
  • 在chrome / firefox中删除事件监听器会立即阻止处理程序被称为WHEREAS,即已经附加在元素上的处理程序将触发,但removeEventListener的效果将发生在下一个tick < / strong>发动机。

这就是为什么,在两种情况下(即和firefox / chrome),第一次点击不会触发功能-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。