简体   繁体   English

添加带有参数的事件侦听器,然后将其删除

[英]Add an event listener with parameters and then remove it

The basic scenario 基本方案

This question has been asked before. 这个问题已经被问过了。 In fact, it's been asked with nearly the same title but please stick with me for a moment, I don't think the question has a good answer yet. 实际上,有人问它标题几乎相同,但请稍等一下,我认为问题尚未解决。

So, we have an event listener: 因此,我们有一个事件监听器:

fancyButton.addEventListener('click', this.launchKitty, true);

And then we have a function: 然后我们有一个函数:

// assume this.setForLaunch was set somewhere
launchKitty = () => {
  if(this.setForLaunch){ // behold, this!
    console.log('farewell, feline!')
  }
}

We have an event listener and a function with access to the outer this , which is neat. 我们有一个事件监听器和一个可以访问外部this的函数,它很简洁。 Removal is easy: 拆卸很容易:

fancyButton.removeEventListener('click', this.launchKitty, true);

But what if we didn't want to use this ? 但是,如果我们不想使用this呢?

Parameters! 参数!

What if, instead of leaning on this , we wanted to pass addEventListener an argument? 如果我们不是想依赖this ,而是想给addEventListener传递一个参数怎么办? Like so: 像这样:

fancyButton.addEventListener('click', () => {this.launchKitty(true)}, true);

And a slightly modified launchKitty() : 以及稍微修改的launchKitty()

launchKitty(setForLaunch) {
  if(setForLaunch){ // now we're using a parameter!
    console.log('farewell, feline!')
  }
}

So far, so good. 到现在为止还挺好。 Kitties are launched. 小猫被发射了。 What about removing the listener? 删除监听器呢?

fancyButton.removeEventListener('click', () => {this.launchKitty}, true);

Not going to work. 不上班 Our () => {} is anonymous and therefore removeEventListener doesn't know how to find it. 我们的() => {}是匿名的,因此removeEventListener不知道如何找到它。

The question 问题

How can we pass an event listener a parameter and then later remove said event handler? 我们如何向事件监听器传递参数,然后再删除所说的事件处理程序?

Please feel free to challenge any of my assumptions. 请随时挑战我的任何假设。 There are a lot of ways to launch this cat. 有很多方法可以发射这只猫。

Thanks! 谢谢!

You should store the currently anonymous function into a variable, so that you can call removeEventListener with it later: 您应该将当前匿名函数存储到变量中,以便稍后可以使用它调用removeEventListener

const launchKittyTrue = () => { this.launchKitty(true) };
fancyButton.addEventListener('click', launchKittyTrue, true);
// later:
fancyButton.removeEventListener('click', launchKittyTrue, true);

To be more flexible, you might consider a Map indexed by arguments, whose values are the bound functions: 为了更加灵活,您可以考虑按参数索引的Map ,其值是绑定函数:

const boundFns = new Map();
function makeListener(arg) {
  if (!boundFns.has(arg)) {
    boundFns.set(arg, launchKitty.bind(undefined, arg));
  }
  return boundFns.get(arg);
}
function getListener(arg) {
  return boundFns.get(arg);
}
fancyButton.addEventListener('click', makeListener(true), true);
// later:
fancyButton.removeEventListener('click', getListener(true), true);

Alternatively to @CertainPerformance's answer. 替代@CertainPerformance的答案。 You can use the bind method from the Function prototype to instantiate a 'copy' of the function with parameters bound to it. 您可以使用Function原型中的bind方法来实例化带有绑定参数的函数的“副本”。

Something like: 就像是:

 function launchKitty(setForLaunch) { console.log(`launchKitty called with setForLaunch = ${setForLaunch}`); } let fancyTrue = launchKitty.bind(null, true); let fancyFalse = launchKitty.bind(null, false); let fancyButton = document.getElementById('fancyButton'); let lessFancyButton = document.getElementById('lessFancyButton'); let detachButton = document.getElementById('detachFancyButton'); fancyButton.addEventListener('click', fancyTrue, true); lessFancyButton.addEventListener('click', fancyFalse, true); detachButton.addEventListener('click', () => { fancyButton.removeEventListener('click', fancyTrue, true); lessFancyButton.removeEventListener('click', fancyFalse, true); }); 
 <button id='fancyButton'>Console Log</button> <button id='lessFancyButton'>No Console Log</button> <button id='detachFancyButton'>Detach Handlers</button> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM