带有 addEventListener 的循环对于 function() 不是动态的
Loop with addEventListener is not dynamic for function()
我想制作一个非常简单的 for 循环来为每个按钮调用一个具有不同参数的函数。但是,当我 运行 调用并单击按钮时,eventListener 函数 saveList(listIdx) 仅 returns 函数 saveList("5")。请看看我的问题和故障排除。
for (var listIdx = 0; listIdx < count; listIdx++ ) {
console.log("setting the variable" + "myButton" + listIdx );
document.getElementById("myButton" + listIdx).addEventListener("click", function() { saveList(listIdx);
});
}
尝试 1:向 function() 调用添加参数
for (var listIdx = 0; listIdx < count; listIdx++ ) {
console.log("setting the variable" + "myButton" + listIdx );
document.getElementById("myButton" + listIdx).addEventListener("click", function(listIdx) { saveList(listIdx);
});
}
尝试 2:元素上的包装器
for (var listIdx = 0; listIdx < count; listIdx++ ) {
console.log("setting the variable" + "myButton" + listIdx );
document.getElementById("myButton" + listIdx).addEventListener("click", function(_listIdx) { saveList(_listIdx);
});
}
问题是函数在稍后的时间点被调用——在 for 循环完成之后。主体中包含的变量已经在 for 循环的最后一次迭代中被更新。这就是您所看到的。
解决方法是以某种方式将变量推送到内部函数。
function makeListSaver(index) {
/* return a brand new function that has captured the index when this function
was invoked
*/
return function() {
saveList(index);
}
}
然后做,
document.getElementById("myButton" + listIdx).addEventListener("click", makeListSaver(listIdx))
或者简单地说,
document.getElementById("myButton" + listIdx).addEventListener("click", (function(index){
return function() { saveList(index); }
})(listIdx));
您需要稍微了解一下闭包及其工作原理。
问题出在循环上。
这里是如何在 for
循环中设置 addEventListener
的简单示例。
http://jsbin.com/kavowucimi/1/
它是如何工作的:
- 页面加载时
- 查找具有 class 对象的所有元素。
- 为每个元素添加一个事件监听器 click。
- 当用户单击时,提醒所选元素的 ID。
<script>
window.app = {
start: function(){
var elms = document.querySelectorAll('.obj');
for (var i = 0; i < elms.length; i++ ) {
var t = elms[i];
var elm = document.getElementById(t.id);
elm.addEventListener('click', function(item){
alert(item.currentTarget.id);
});
}
}
};
</script>
<body onload="window.app.start();">
<div id=1 class="obj">1</div>
<div id=2 class="obj">2</div>
<div id=3 class="obj">3</div>
你可以这样做...
for (var listIdx = 0; listIdx < count; listIdx++ ) {
applyEvent(listIdx);
}
function applyEvent(listIdx)
{
document.getElementById("1" + listIdx).addEventListener("click", function({
saveList(listIdx);
});
}
工作Fiddle
我想制作一个非常简单的 for 循环来为每个按钮调用一个具有不同参数的函数。但是,当我 运行 调用并单击按钮时,eventListener 函数 saveList(listIdx) 仅 returns 函数 saveList("5")。请看看我的问题和故障排除。
for (var listIdx = 0; listIdx < count; listIdx++ ) {
console.log("setting the variable" + "myButton" + listIdx );
document.getElementById("myButton" + listIdx).addEventListener("click", function() { saveList(listIdx);
});
}
尝试 1:向 function() 调用添加参数
for (var listIdx = 0; listIdx < count; listIdx++ ) {
console.log("setting the variable" + "myButton" + listIdx );
document.getElementById("myButton" + listIdx).addEventListener("click", function(listIdx) { saveList(listIdx);
});
}
尝试 2:元素上的包装器
for (var listIdx = 0; listIdx < count; listIdx++ ) {
console.log("setting the variable" + "myButton" + listIdx );
document.getElementById("myButton" + listIdx).addEventListener("click", function(_listIdx) { saveList(_listIdx);
});
}
问题是函数在稍后的时间点被调用——在 for 循环完成之后。主体中包含的变量已经在 for 循环的最后一次迭代中被更新。这就是您所看到的。
解决方法是以某种方式将变量推送到内部函数。
function makeListSaver(index) {
/* return a brand new function that has captured the index when this function
was invoked
*/
return function() {
saveList(index);
}
}
然后做,
document.getElementById("myButton" + listIdx).addEventListener("click", makeListSaver(listIdx))
或者简单地说,
document.getElementById("myButton" + listIdx).addEventListener("click", (function(index){
return function() { saveList(index); }
})(listIdx));
您需要稍微了解一下闭包及其工作原理。
问题出在循环上。
这里是如何在 for
循环中设置 addEventListener
的简单示例。
http://jsbin.com/kavowucimi/1/
它是如何工作的:
- 页面加载时
- 查找具有 class 对象的所有元素。
- 为每个元素添加一个事件监听器 click。
- 当用户单击时,提醒所选元素的 ID。
<script>
window.app = {
start: function(){
var elms = document.querySelectorAll('.obj');
for (var i = 0; i < elms.length; i++ ) {
var t = elms[i];
var elm = document.getElementById(t.id);
elm.addEventListener('click', function(item){
alert(item.currentTarget.id);
});
}
}
};
</script>
<body onload="window.app.start();">
<div id=1 class="obj">1</div>
<div id=2 class="obj">2</div>
<div id=3 class="obj">3</div>
你可以这样做...
for (var listIdx = 0; listIdx < count; listIdx++ ) {
applyEvent(listIdx);
}
function applyEvent(listIdx)
{
document.getElementById("1" + listIdx).addEventListener("click", function({
saveList(listIdx);
});
}
工作Fiddle