按类删除所有eventListeners

时间:2018-01-24 03:29:54

标签: javascript event-listener

我正在使用第一个代码块将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);
    });
}

3 个答案:

答案 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>