带参数的Javascript事件处理程序

seb*_*day 74 javascript events event-handling handler

我想创建一个传递事件和一些参数的eventHandler.问题是函数没有得到元素.这是一个例子:

doClick = function(func){
    var elem = .. // the element where it is all about
    elem.onclick = function(e){
        func(e, elem);
    }
}
doClick(function(e, element){
    // do stuff with element and the event
});
Run Code Online (Sandbox Code Playgroud)

'elem'必须在匿名函数之外定义.如何在匿名函数中获取传递的元素?有没有办法做到这一点?

那么addEventListener呢?我似乎无法通过addEventListener传递事件吗?

更新

我好像用'这个'解决了这个问题

doClick = function(func){
    var that = this;
    this.element.onclick = function(e){
        func(e, that);
    }
}
Run Code Online (Sandbox Code Playgroud)

这包含我可以在函数中访问的this.element.

addEventListener

但我想知道addEventListener:

function doClick(elem, func){
    element.addEventListener('click', func(event, elem), false);
}
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 84

我不明白你的代码究竟在做什么,但你可以使用函数闭包的优点在任何事件处理程序中使变量可用:

function addClickHandler(elem, arg1, arg2) {
    elem.addEventListener('click', function(e) {
        // in the event handler function here, you can directly refer
        // to arg1 and arg2 from the parent function arguments
    }, false);
}
Run Code Online (Sandbox Code Playgroud)

根据您的确切编码情况,您几乎总能使某种闭包保留对变量的访问权限.

根据您的评论,如果您要完成的是:

element.addEventListener('click', func(event, this.elements[i]))
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用自执行函数(IIFE)执行此操作,该函数在执行时捕获闭包中所需的参数并返回实际的事件处理函数:

element.addEventListener('click', (function(passedInElement) {
    return function(e) {func(e, passedInElement); };
}) (this.elements[i]), false);
Run Code Online (Sandbox Code Playgroud)

有关IIFE如何工作的更多信息,请参阅以下其他参考:

Javascript包装匿名函数内的代码

立即调用函数表达式(IIFE)在JavaScript中 - 传递jQuery

JavaScript自行执行匿名函数有哪些好的用例?

最后一个版本可能更容易看到它正在做的事情:

// return our event handler while capturing an argument in the closure
function handleEvent(passedInElement) {
    return function(e) {
        func(e, passedInElement); 
    };
}

element.addEventListener('click', handleEvent(this.elements[i]));
Run Code Online (Sandbox Code Playgroud)

也可以使用.bind()向回调添加参数.您传递给的任何参数都.bind()将被添加到回调本身将具有的参数之前.所以,你可以这样做:

elem.addEventListener('click', function(a1, a2, e) {
    // inside the event handler, you have access to both your arguments
    // and the event object that the event handler passes
}.bind(elem, arg1, arg2));
Run Code Online (Sandbox Code Playgroud)

  • @ sebas2day - 你不能做`element.addEventListener('click',func(event,this.elements [i]))`.Javascript只是不起作用.还有其他方法,使用闭包,但你不能按照你写的方式去做.addEventListener只用一个参数(事件)调用它的回调,你不能以任何方式改变它. (4认同)
  • 关闭...自切片面包以来最好的事情。 (2认同)
  • @ Bosh19 - 看看我在答案末尾添加了什么来解释您所询问的构造。它是一个立即调用的函数表达式 (IIFE),它本质上是一个立即执行的匿名声明的函数。这是定义函数然后调用它的快捷方式 - 当您希望内联主体并且不会在其他任何地方调用它时非常有用,因此它不需要名称。 (2认同)

Snn*_*Snn 23

这是一个古老的问题,但却很常见.所以让我在这里添加这个.

使用ES2015语法,您可以更简洁地实现它:

const event_handler = (event, arg) => console.log(event, arg);
el.addEventListener('click', (event) => event_handler(event, 'An argument'));
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是一个合理的解决方案,但是当您必须删除相同的事件侦听器时呢? (2认同)

Kni*_*shi 9

您可以尝试使用绑定方法,我认为这可以实现您的要求.如果不出意外,它仍然非常有用.

function doClick(elem, func) {
  var diffElem = document.getElementById('some_element'); //could be the same or different element than the element in the doClick argument
  diffElem.addEventListener('click', func.bind(diffElem, elem))
}

function clickEvent(elem, evt) {
  console.log(this);
  console.log(elem); 
  // 'this' and elem can be the same thing if the first parameter 
  // of the bind method is the element the event is being attached to from the argument passed to doClick
  console.log(evt);
}

var elem = document.getElementById('elem_to_do_stuff_with');
doClick(elem, clickEvent);
Run Code Online (Sandbox Code Playgroud)