addEventListener使用循环和传递值
我正尝试添加事件监听器使用for循环的多个对象,但最终所有的监听器针对同一个对象 – >最后一个。
如果我通过为每个实例定义boxa和boxb来手动添加侦听器,它将起作用。 我想这是addEvent for-loop,这不是我所希望的。 也许我完全用错了方法。
使用class =“container”中的4的示例容器4上的触发按其应有的方式工作。 触发容器1,2,3上的容器1,2,3触发事件,但只有在触发器已被激活的情况下。
任何帮助将不胜感激
点击运行function:
function makeItHappen(elem, elem2){ var el = document.getElementById(elem); el.style.transform = "flip it"; var el2 = document.getElementById(elem2); el2.style.transform = "flip it"; }
自动加载function添加监听器:
function addEvents(){ var elem = document.getElementsByClassName("triggerClass"); for(var i=0; i < elem.length; i+=2){ var k = i + 1; var boxa = elem[i].parentNode.id; var boxb = elem[k].parentNode.id; elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false); elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false); } }
HTML代码
<div class="container"> <div class="one" id="box1"> <p class="triggerClass">some text</p> </div> <div class="two" id="box2"> <p class="triggerClass">some text</p> </div> </div> <div class="container"> <div class="one" id="box3"> <p class="triggerClass">some text</p> </div> <div class="two" id="box4"> <p class="triggerClass">some text</p> </div> </div>
瓶盖! :d
这个固定的代码按照你的意图工作:
for (var i = 0; i < elem.length; i += 2) { (function () { var k = i + 1; var boxa = elem[i].parentNode.id; var boxb = elem[k].parentNode.id; elem[i].addEventListener("click", function() { makeItHappen(boxa,boxb); }, false); elem[k].addEventListener("click", function() { makeItHappen(boxb,boxa); }, false); }()); // immediate invocation }
为什么这个修复它?
for(var i=0; i < elem.length; i+=2){ var k = i + 1; var boxa = elem[i].parentNode.id; var boxb = elem[k].parentNode.id; elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false); elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false); }
实际上是非严格的JavaScript。 这是这样解释的:
var i, k, boxa, boxb; for(i=0; i < elem.length; i+=2){ k = i + 1; boxa = elem[i].parentNode.id; boxb = elem[k].parentNode.id; elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false); elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false); }
由于variables提升 , var
声明被移动到范围的顶部。 由于JavaScript没有块范围(例如, if
,等等),他们被移动到函数的顶部。 更新:从ES6开始,您可以使用let
来获取块范围的variables。
当你的代码运行时,会发生以下情况:在for
循环中添加单击callbackboxa
,并指定boxa
,但是在下一次迭代中它的值被覆盖。 当click事件触发callback运行时, boxa
的值始终是列表中的最后一个元素。
使用闭包(closuresboxa
, boxb
等的值)将值绑定到click处理程序的范围。
代码分析工具,如JSLint或JSHint将能够捕获像这样的可疑代码。 如果你写了很多代码,花时间学习如何使用这些工具是值得的。 一些IDE有内置的。
你面临的范围/closures问题作为function(){makeItHappen(boxa,boxb);}
boxa和boxb引用,然后总是最后一个元素(S)。
要解决这个问题:
function makeItHappenDelegate(a, b) { return function(){ makeItHappen(a, b) } } // ... elem[i].addEventListener("click", makeItHappenDelegate(boxa,boxb), false);
你可以使用函数绑定。你不需要使用闭包。参见下面:
之前 :
function addEvents(){ var elem = document.getElementsByClassName("triggerClass"); for(var i=0; i < elem.length; i+=2){ var k = i + 1; var boxa = elem[i].parentNode.id; var boxb = elem[k].parentNode.id; elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false); elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false); } }
之后 :
function addEvents(){ var elem = document.getElementsByClassName("triggerClass"); for(var i=0; i < elem.length; i+=2){ var k = i + 1; var boxa = elem[i].parentNode.id; var boxb = elem[k].parentNode.id; elem[i].addEventListener("click", makeItHappen.bind(this, boxa, boxb), false); elem[k].addEventListener("click", makeItHappen.bind(this, boxa, boxb), false); } }
这是因为closures。
看看这个: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Creating_closures_in_loops_A_common_mistake
示例代码和代码基本相同,对于那些不知道“closures”的人来说,这是一个常见的错误。
简单来说,当你在addEvents()
里面创build一个处理函数时,它不仅仅是从addEvents()
的环境中访问variablesi
,而且还会“记住” i
。
而且因为你的处理程序“记得” i
,variablesi
不会在addEvents()
执行后消失。
所以当处理程序被调用时,它将使用i
但variablesi
现在,在for循环后,3。
我前一阵子也有这个问题。 我通过在循环之外使用“增加”function来解决它,分配事件,并完美的工作。
你的脚本应该看起来像。
function addEvents(){ var elem = document.getElementsByClassName("triggerClass"); for(var i=0; i < elem.length; i+=2){ var k = i + 1; var boxa = elem[i].parentNode.id; var boxb = elem[k].parentNode.id; //- edit ---------------------------| adds(boxa, boxb); } } //- adds function ----| function adds(obj1, obj2){ obj1.addEventListener("click", function(){makeItHappen(obj1, obj2);}, false); obj2.addEventListener("click", function(){makeItHappen(obj1, obj2);}, false); } //- end edit -----------------------| function makeItHappen(elem, elem2){ var el = document.getElementById(elem); el.style.transform = "flip it"; var el2 = document.getElementById(elem2); el2.style.transform = "flip it"; }