如何删除JavaScript中动态生成的事件处理程序



当我单击按钮时,我会看到控制台消息,显示我已经单击了它们。当我取消选中复选框,然后单击按钮时,我希望没有控制台消息,但我仍然可以看到它们。为什么removeEventListener不删除事件侦听器?

const buttons = document.querySelectorAll('ul li button');
function initialize() {
for (let i = 0; i < buttons.length; i++) {
function doSomething() {
console.log(`You clicked on ${buttons[i].textContent}`);
}
if (document.querySelector('#mode').checked) {
buttons[i].addEventListener('click', doSomething);
} else {
buttons[i].removeEventListener('click', doSomething);
}
}
}
document.querySelector('#mode').addEventListener('click', initialize);
initialize();
<input id='mode' type='checkbox' checked/>
<label for='mode'>Do something when you click</label>
<ul>
<li><button>One</button>
<li><button>Two</button>
<li><button>Three</button>
<li><button>Four</button>

我不能在for循环之外定义doSomething,因为我需要i来做其他事情(为了简单起见,这里没有显示(。我确实需要为每个索引使用不同的处理程序。

目前,doSomething是在for循环中定义的,这意味着每次执行initialize时,都会得到一个名为doSomething的新函数。因此,addEventListener添加了一个称为doSomething的函数,而removeEventListener尝试删除另一个函数(也称为doSomething(。新的doSomething从未注册为事件侦听器,因此无法删除它,而旧的doSomething超出了范围,因此我们无法引用它来删除它。相反,您可以动态生成一次函数,并在initialize中引用它们。

const buttons = document.querySelectorAll('ul li button');
const buttonFunctions = [];
for (let i = 0; i < buttons.length; i++) {
buttonFunctions[i] = function doSomething() {
console.log(`You clicked on ${buttons[i].textContent}`);
}
}

function initialize() {
for (let i = 0; i < buttons.length; i++) {
if (document.querySelector('#mode').checked) {
buttons[i].addEventListener('click', buttonFunctions[i]);
} else {
buttons[i].removeEventListener('click', buttonFunctions[i]);
}
}
}
document.querySelector('#mode').addEventListener('click', initialize);
initialize();
<input id='mode' type='checkbox' checked/>
<label for='mode'>Do something when you click</label>
<ul>
<li><button>One</button>
<li><button>Two</button>
<li><button>Three</button>
<li><button>Four</button>

最新更新