在使用匿名函数传递参数时,addEventListener会为同一句柄多次触发

时间:2014-10-01 16:30:40

标签: javascript events javascript-events anonymous-function addeventlistener

由于某种原因,当将参数传递给匿名函数时,事件侦听器会为每个元素触发两次。即,元素el上的click事件将注册一次,因此触发一次。

el.addEventListener("click", handle, false);
el.addEventListener("click", handle, false);

但是如果我想将自己的参数传递给它,它会注册并触发两次。

el.addEventListener("click", function() { handle(event, myArgument); }, false);
el.addEventListener("click", function() { handle(event, myArgument); }, false);

问题是为什么以及解决方案是什么?

我在别处寻找,似乎无法找到解决方案或理解为什么会出现这个问题。我尝试在How to pass an argument to the listener function passed in addEventListener?中实施解决方案,但他们没有帮助 -

我做了基本的匿名函数或闭包,然后是更高级的版本,如下所示,但确实有效。

我不知道为什么传递没有参数导致元素事件注册一次并传递参数导致元素事件注册两次。

以下是代码:

<html>
    <head>
        <script type="text/javascript">
            var handle_2 = function(evt, type) {
                var test;
                switch (type) {
                    case "focus": 
                        console.log(evt.target.value);
                        break;
                    case "click":
                        console.log(evt.target.id + " was clicked");
                        break;
                    default: console.log("no type found");
                }
            };

            window.onload = function() {
                var textbox = document.getElementById("t1");
                var button = document.getElementById("btn");
                textbox.value = "456";
                button.value = "Press";

                var typeFocus = "focus", typeClick = "click";

                textbox.addEventListener("focus", (function(typeFocus) { return function(evt) { handle_2(evt, typeFocus); }})(typeFocus), false);
                button.addEventListener("click", (function(typeClick) { return function(evt) { handle_2(evt, typeClick); }})(typeClick), false);

                // Registers again for each element. Why?
                textbox.addEventListener("focus", (function(typeFocus) { return function(evt) { handle_2(evt, typeFocus); }})(typeFocus), false);
                button.addEventListener("click", (function(typeClick) { return function(evt) { handle_2(evt, typeClick); }})(typeClick), false);
            };
        </script>
    </head>
    <body>
        <div id="wrapper">
            <input id="t1" type="text" />
            <input id="btn" type="button" />
        </div>
    </body>
</html>

任何帮助将不胜感激。谢谢。

3 个答案:

答案 0 :(得分:18)

最简单的解决方案是仅创建一个新处理程序:

var newHandle = function(event) { handle(event, myArgument); };

el.addEventListener("click", newHandle, false);
el.addEventListener("click", newHandle, false);

答案 1 :(得分:2)

好,,

el.addEventListener("click", handle, false);
el.addEventListener("click", handle, false);

注册到相同的功能&#34; handle()&#34;

el.addEventListener("click", function() { handle(event, myArgument); }, false);
el.addEventListener("click", function() { handle(event, myArgument); }, false);

注册&#34; function(){handle(event,myArgument)&#34; ...这是两个独特的匿名函数。因此会发射两次。

虽然我不完全理解你为什么要注册两次,但解决办法是创建一个函数来返回带参数的函数。

el.addEventListener("click", crateHandle(myArgument), false);

var createHandle = function(myArgument) {
  return function(event) {
    .... do something
  };
}

但它仍然没有解决两次火问题。

答案 2 :(得分:0)

addEventListener注册的侦听器数量与使用的数量相同。

根据documentation,它需要3个参数,第三个是useCapture,它与注册侦听器两次无关。它默认设置为false,因此添加false作为第三个参数不会发生太大变化。