removeEventListener 在 JavaScript 中不起作用

removeEventListener 方法可能不起作用的原因有多种:

  1. 没有将相同的函数传递给 addEventListener 和 removeEventListener 方法。
  2. 使用 bind 方法,它在调用 removeEventListener 时返回一个新函数。
  3. 在与 addEventListener 方法不同的 DOM 元素上调用 removeEventListener
  4. 两次注册事件侦听器 – 使用和不使用捕获标志。

这是问题的最常见原因 – 将 2 个不同的函数传递给 addEventListener() 和 removeEventListener() 方法。

const btn = document.getElementById('btn');

btn.addEventListener('click', function logger() {
  console.log('Button clicked');
});

// ⛔️ Doesn't work - we define another function
btn.removeEventListener('click', function logger() {
  console.log('Button clicked');
});

我们传递给这两个方法的函数看起来是一样的,但是,这是两个不同的函数,在内存中的位置完全不同。

对于 JavaScript 引擎,这两个函数没有任何关系。

相反,我们应该定义函数并将相同的引用传递给 addEventListener 和 removeEventListener 方法。

const btn = document.getElementById('btn');

function logger() {
  console.log('Button clicked');
}

btn.addEventListener('click', logger);

// ✅ Works
btn.removeEventListener('click', logger);

我们向这两种方法传递了相同的引用,因此 removeEventListener 方法按预期工作。

removeEventListener 方法不起作用的另一个常见原因是使用 bind 方法,该方法返回一个新函数。

const btn = document.getElementById('btn');

function logger() {
  console.log('Button clicked');
}

btn.addEventListener('click', logger);

// ⛔️ Doesn't work - bind returns a new function
btn.removeEventListener('click', logger.bind(null));

bind() 方法使用提供的 this 值和初始参数返回给定函数的副本。

为了避免这个问题,我们可以将调用 bind() 方法的返回值分配给一个变量,并将其传递给 addEventListener 和 removeEventListener 方法。

const btn = document.getElementById('btn');

function logger() {
  console.log('Button clicked');
}

const boundLogger = logger.bind(null);

btn.addEventListener('click', boundLogger);

// ✅ Works
btn.removeEventListener('click', boundLogger);

removeEventListener 方法不起作用的另一个常见原因是在另一个 DOM 元素上调用该方法。

const btn = document.getElementById('btn');

function logger() {
  console.log('Button clicked');
}

btn.addEventListener('click', logger);

// 👇️ Different DOM element
const blueBtn = document.getElementById('blue-btn');

// ⛔️ Doesn't work called on different DOM element
blueBtn.removeEventListener('click', logger);

要解决此问题,请确保在调用 addEventListener 方法的同一元素上调用 removeEventListener 方法。

最后,如果我们两次调用 addEventListener 方法,我们也可能会遇到此行为 – 一次没有捕获,一次有捕获。

const btn = document.getElementById('btn');

function logger() {
  console.log('Button clicked');
}

btn.addEventListener('click', logger, true);
btn.addEventListener('click', logger, false);

// ⛔️ Doesn't work registered with and without capture
btn.removeEventListener('click', logger);

要解决此问题,我们必须分别删除每个事件侦听器。

const btn = document.getElementById('btn');

function logger() {
  console.log('Button clicked');
}

btn.addEventListener('click', logger, true);
btn.addEventListener('click', logger, false);

// ✅ Works
btn.removeEventListener('click', logger, true);
btn.removeEventListener('click', logger, false);

我们必须两次调用 removeEventListener 方法来删除这两个事件——一个设置了捕获标志,另一个没有。


总结

要解决 removeEventListener 不工作的问题,请确保将相同的函数传递给 addEventListener 和 removeEventListener 方法。 传递指向内存中不同位置的函数不会删除监听器。