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

时间:2019-01-06 05:31:44

标签: javascript

基本情况

此问题曾被问过。实际上,有人问过with nearly the same title,但请稍等一下,我认为问题尚未解决。

因此,我们有一个事件侦听器:

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

然后我们有一个函数:

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

我们有一个事件侦听器和一个可以访问外部this的函数,它很简洁。移除很容易:

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

但是如果我们不想使用this怎么办?

参数!

如果我们不想依靠this,而是想给addEventListener传递参数,该怎么办?像这样:

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

还有一个稍微修改过的launchKitty()

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

到目前为止,太好了。小猫被发射了。删除监听器怎么办?

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

不上班。我们的() => {}是匿名的,因此removeEventListener不知道如何找到它。

问题

我们如何为事件侦听器传递一个参数,然后再删除该事件处理程序?

请随时挑战我的任何假设。有很多方法可以发射这只猫。

谢谢!

2 个答案:

答案 0 :(得分:4)

您应该将当前匿名函数存储到变量中,以便以后可以使用它来调用removeEventListener

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

为更加灵活,您可以考虑使用参数作为索引的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);

答案 1 :(得分:1)

或者@CertainPerformance的答案。您可以使用Function原型中的bind方法来实例化带有绑定参数的函数的“副本”。

类似的东西:

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>