使用JavaScript添加和删除带参数的事件监听器并访问元素和事件?

8
假设我想向函数传递参数。我听说应该通过在函数内部调用另一个函数来实现,像这样:
myElement.addEventListener("click",function whatever(event){
    myFunk(event,"some argument");
},false);

但是如果我现在想要移除它呢?

myElement.removeEventListener("click",whatever,false);

var myElement = document.querySelector('div')
function myFunk(e,m){
  console.log(e,m)
}
myElement.addEventListener("click",function whatever(event){
    myFunk(event,"some argument")
},false)

myElement.removeEventListener("click", whatever, false)
<div></div>

这会在控制台返回一个“未定义的错误”。所以我的函数没有名字吗?“whatever”不是它的名字吗?那么现在如何删除它?
我需要一种方法来分配一个事件侦听器并传递参数,然后稍后将其删除。我该怎么做?
编辑:
好的,是的,我不能引用“whatever”,因为它是内联编写的。但我被迫使用内联函数表达式的原因是我想传递参数。我想传递参数是因为我不想每次更改行为时都要定义一个新函数。如果我使用“on”属性上的文本定义事件侦听器,我可以轻松交换参数:
element.onClick("myFunc('do one thing')");
element.onClick("myFunc('do a different thing')");
如何使用addEventListener,在内联中,可移除且具有动态参数?

你的问题是 whatever 并不是一个函数,而是一个函数表达式,在调用 myElement.addEventListener 函数后,whatever 就不再可用了。但你可以像这样在内部使用 whateverfunction whatever(){...; whatever();} - Grundy
那么我该如何使用参数? - ADJenks
我将'myFunc'包装在'whatever'中的唯一原因是为了能够向函数传递参数。我希望能够在事件上调用带有参数的函数,然后删除该函数,然后稍后重新添加具有不同参数的函数,以使其表现不同。 - ADJenks
你如何定义应该使用哪个参数? - Grundy
你能提供一个小的可工作的 jsfiddle 吗?里面包含你做过和尝试过的内容? - Grundy
3个回答

10
< p >对于 addEventListener() 的第二个参数,执行以下操作:

whatever= function(event) {
  ...
}

...取而代之:

function whatever(event) {
  ...
}

您可以按照以下步骤删除事件:

myElement.removeEventListener('click' , whatever);

使用 bind 来向另一个事件传递参数,方法如下:
whatever= myfunk.bind(myElement, parameter1, parameter2, ...)

示例

var myElement= document.getElementById('myElement');

function myfunk(s) {
  this.innerHTML+= '<br>'+s;
  myElement.removeEventListener('click', whatever);

  myElement.addEventListener(
    'click',
    whatever= myfunk.bind(myElement, 'Clicked again.')
  );
}

myElement.addEventListener(
  'click',
  whatever= myfunk.bind(myElement, 'Clicked once.')
);
<div id="myElement">Click me!</div>


1
但在这种情况下,whatever被添加到全局对象中。 - Grundy
True。如果这是在函数内部,我们可以在事件监听器之前添加var whatever;。但我认为大多数事件处理程序都应该在全局范围内定义。 - Rick Hitchcock
我无法向函数传递参数。 - ADJenks
1
绑定!就是这样!绑定!非常感谢。现在我的大脑很轻松。 - ADJenks
回顾这个问题,我可能也可以使用工厂模式。 - ADJenks

1
也许这会帮助你实现你的目标...generateHandler为输入函数生成事件处理程序函数,带有一个输入参数,并将“真正的处理程序”传递给事件、参数和处理程序实例,以便轻松地删除。它还返回该实例,以便从外部删除处理程序。
然后我展示了各种使用方式。希望这能帮到你...

function generateHandler(f, arg) {
  var handler = function (evt) {
    f(evt, arg, handler);
  };
  return handler;
}

function realFunc(evt, arg, handler) {
  alert(arg);
  if(arg == 2) {
    document.getElementById('el').removeEventListener('click', handler);
    document.getElementById('el').innerHTML = 'I also do nothing now';
  }
}

function replace1Time(evt, arg, handler) {
  document.getElementById('el').removeEventListener('click', elHandler);
  elHandler = generateHandler(realFunc, 2);
  document.getElementById('el').addEventListener('click', elHandler);
  document.getElementById('el2').removeEventListener('click', handler);
  document.getElementById('el2').innerHTML = 'I do nothing now';
}

var elHandler = generateHandler(realFunc, 1);

document.getElementById('el').addEventListener('click', elHandler);
document.getElementById('el2').addEventListener('click', generateHandler(replace1Time));
<div id="el">Click me!</div>
<div id="el2">Click me to replace 1 time</div>


如果我想要添加一个使用不同参数的新侦听器,那么每次我都必须定义一个新函数来传递参数给它真正的函数。我真的需要每次都定义一个新函数,然后在第二个函数中更改参数吗? - ADJenks
@adjenks,不太清楚什么才算是“足够好”,但我给你提供了一个更加灵活的解决方案。 - Amit

0

看一下这个fiddle

当你按下按钮时,会看到一个警报,但之后不会再看到它,因为它已从监听器中移除。

function anotherFunctionWithParams(param1, param2){
      alert (param1 + "-" + param2);
}

var cbFunc= function(){
  anotherFunctionWithParams("tra","lalala");
  document.getElementById("test").removeEventListener("click", cbFunc);
}


document.getElementById("test").addEventListener("click", cbFunc, false);

此外请注意,您 不能 删除内联匿名监听函数。


如果我想要添加一个带有不同参数的新监听器,那么每次我想要传递参数时,我都必须定义一个新函数。我真的需要每次都定义一个新函数,然后更改第二个函数中的参数吗? - ADJenks
@adjenks 你能使用 jQuery 吗? - Alp
1
如果jQuery可以做到,那么使用普通的JavaScript肯定也行。不过,我很愿意看一下用jQuery的答案,然后也许我可以检查一下jQuery库是如何实现的。 - ADJenks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接