增加多个具有点击事件的按钮
增加多个具有点击事件的按钮
这个问题已经有了答案:
JavaScript循环内的闭包-简单实际例子
我想使用for循环为多个对象添加事件侦听器,但最终所有侦听器都指向同一个对象->最后一个对象。
如果我手动定义每个实例的boxa和boxb来添加侦听器,则可以工作。我猜是addEvent for-loop没有按照我希望的方式工作。也许我整个使用的方法不正确。
使用class="container"的4个示例
容器4上的触发器按预期工作。
容器1,2,3上的触发器会在容器4上触发事件,但仅当触发器已被激活时。
// Function to run on click: function makeItHappen(elem, elem2) { var el = document.getElementById(elem); el.style.backgroundColor = "red"; var el2 = document.getElementById(elem2); el2.style.backgroundColor = "blue"; } // Autoloading function to add the listeners: 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); }
some text
some text
some text
some text
admin 更改状态以发布 2023年5月21日
你可以使用函数绑定。你不需要使用闭包。见下面的示例:
之前:
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); } }
闭包!:D
这个修复的代码按照你的意图工作:
// Function to run on click: function makeItHappen(elem, elem2) { var el = document.getElementById(elem); el.style.backgroundColor = "red"; var el2 = document.getElementById(elem2); el2.style.backgroundColor = "blue"; } // Autoloading function to add the listeners: var elem = document.getElementsByClassName("triggerClass"); 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 }
some text
some text
some text
some text
为什么这样修复它?
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); }
由于变量提升,var
声明被移动到作用域的顶部。由于JavaScript没有块级作用域(如for
、if
、while
等),它们被移动到函数的顶部。更新:自ES6以来,您可以使用let
获取块级作用域变量。
当你的代码运行时,以下步骤发生:在for
循环中,你添加了点击回调并分配了boxa
,但它的值在下一次迭代中被覆盖。当点击事件触发时,回调运行并且boxa
的值总是列表中的最后一个元素。
使用闭包(关闭boxa
、boxb
等的值),你将值绑定到点击处理程序的作用域。
代码分析工具(如JSLint或JSHint)将能够捕获这样的可疑代码。如果你写了很多代码,花时间学习如何使用这些工具是值得的。一些IDE已经内置了它们。