我正在使用第一个代码块将eventListeners成功添加到具有相同类的<div>
个标记组,但第二个块几乎完全相同,不会删除它们。有人可以解释为什么会这样吗?
1
let names = document.querySelectorAll('.playerName');
names.forEach((name) => {
name.addEventListener('click', () => {selectSelf(name)});
});
2
function dropEvents() {
let drops = document.querySelectorAll('.playerName');
drops.forEach((drop) => {
drop.removeEventListener('click', () => {selectSelf(name)});
});
}
他们都在使用类<div>
选择同一组.playerName
标记。在selectSelf(name)
上运行的click
函数仅将已点击的<div>
的值分配给变量,运行alert()
(这样我就知道它已成功运行)然后立即调用dropEvents()
函数。因此理论上selectSelf(name)
不应该在第一次之后运行,但确实如此。
对于.removeEventListener
方法,我尝试了许多不同的变体但没有成功。
编辑:我在w3schools页面上看到这种方法匿名函数无法正常工作,这改变了我的问题。我尝试了以下方法,但它也没有用。
function dropEvents() {
let drops = document.querySelectorAll('.playerName');
drops.forEach((drop) => {
drop.removeEventListener('click', selectSelf);
});
}
答案 0 :(得分:3)
removeEventListener()的第二个参数必须是函数引用,但是您传递的是 new ,文字箭头函数。
在该示例中,() => {selectSelf(name)}
的第二次出现是字面上声明的 new 箭头函数。已添加为事件处理程序的那个是不同的函数,因此您不能指望它被删除。
要使其工作,请保存对稍后传递给removeEventListener()
的每个处理函数的引用:
let names = document.querySelectorAll('.playerName');
const handlers = [];
names.forEach((name) => {
// Use a unique identifier for each function reference
handlers[name.id] = () => selectSelf(name);
name.addEventListener('click', handlers[name.id]);
});
function dropEvents() {
let drops = document.querySelectorAll('.playerName');
drops.forEach((drop) => {
drop.removeEventListener('click', handlers[drop.id]);
});
}
答案 1 :(得分:1)
事件处理程序的签名/引用必须相同。在您的代码中,在删除期间,您必须引用相同的功能。以下是解决方案。将click
事件处理程序移动到函数。
let names = document.querySelectorAll('.playerName');
const clickEv = () => {
// selectSelf(name);
console.log('yay');
};
names.forEach((name) => {
name.addEventListener('click', clickEv);
});
function dropEvents() {
let drops = document.querySelectorAll('.playerName');
drops.forEach((drop) => {
drop.removeEventListener('click', clickEv);
});
}
<button type="button" class="playerName">1</button>
<button type="button" class="playerName">2</button>
<button type="button" class="playerName">3</button>
<button type="button" class="playerName">4</button>
<button type="button" class="drop" onClick="dropEvents()">drop</button>
答案 2 :(得分:0)
为了使removeEventListener
能够正常工作,您必须将传递给addEventListener
的相同函数传递给它,而不仅仅是它。
您尝试做的事情的一个复杂因素是使用闭包变量name
,这会创建一种情况,其中每个单独的处理函数都是一个唯一的匿名函数,这样您就不得不保留跟踪您使用的所有功能,然后再次引用它们以删除处理程序。
但这里真的不需要。 name
只是对元素本身的引用,您可以从事件参数(e.target
)获取。
如果你这样做,你可以使用普通的命名函数,而不是为每个元素创建一个单独的函数,并且必须跟踪它们:
let names = document.querySelectorAll('.playerName');
// placeholder
const selectSelf = (el) => console.log(el.textContent);
const clickHandler = (e) => {
selectSelf(e.target);
};
names.forEach((name) => {
name.addEventListener('click', clickHandler);
});
function dropEvents() {
names.forEach((drop) => {
drop.removeEventListener('click', clickHandler);
});
}
document.getElementById('drop').addEventListener('click', dropEvents);
<div class="playerName">Glorgon</div>
<div class="playerName">Marlbratt</div>
<div class="playerName">Xaxir</div>
<div class="playerName">Splengraf</div>
<button type="button" id="drop">Drop Events</button>