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

use*_*236 10 javascript events anonymous-function javascript-events addeventlistener

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

el.addEventListener("click", handle, false);
el.addEventListener("click", handle, false);
Run Code Online (Sandbox Code Playgroud)

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

el.addEventListener("click", function() { handle(event, myArgument); }, false);
el.addEventListener("click", function() { handle(event, myArgument); }, false);
Run Code Online (Sandbox Code Playgroud)

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

我在其他地方寻找,似乎无法找到解决方案或理解为什么会出现这个问题.我尝试在如何将参数传递给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>
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.谢谢.

Fel*_*ing 21

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

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

el.addEventListener("click", newHandle, false);
el.addEventListener("click", newHandle, false);
Run Code Online (Sandbox Code Playgroud)


Ste*_*eck 6

出色地,,

el.addEventListener("click", handle, false);
el.addEventListener("click", handle, false);
Run Code Online (Sandbox Code Playgroud)

注册到相同的函数“handle()”

el.addEventListener("click", function() { handle(event, myArgument); }, false);
el.addEventListener("click", function() { handle(event, myArgument); }, false);
Run Code Online (Sandbox Code Playgroud)

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

尽管我不完全理解为什么您想要注册它两次,但解决方案是创建一个返回带有参数的函数的函数。

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

var createHandle = function(myArgument) {
  return function(event) {
    .... do something
  };
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果 `el.addEventListener("click", crateHandle(myArgument), false);` 被调用两次,您的解决方案也会出现同样的问题。 (2认同)