我有一个包含多个表单(动态创建)的HTML页面,因此我将它们放入JS中的数组中,然后我为每个表单添加EventListener
,如下所示:
var forms = document.getElementsByTagName('form');
for(i=0; i < forms.length; i++) {
forms[i].addEventListener('change', function(){
checkAllFilled(i);
});
}
所以在函数checkAllFilled
中我做了一些事情。
问题在于,如果我有7个表单(从forms[0]
到forms[6]
)并且我在forms[2]
上工作,那么它总是被称为checkAllFilled(7)
,而不是调用{ {1}}。就像在for循环中的最后一个值中设置变量checkAllFilled(2)
一样。
我该怎么做?
谢谢!
答案 0 :(得分:4)
就像变量“i”被设置在for的最后一个值中 循环。
这正是发生的事情。
想一想。在for循环过去之后,您的事件处理程序将在稍后运行。那时,变量具有循环留给它的任何值 - 因此,事件将始终报告相同的单个值。
相反,您需要通过闭包绑定迭代值。有几种方法。一种是通过立即执行的功能(IEF)。
forms[i].addEventListener('change', (function(i) { return function(){
checkAllFilled(i);
}; })(i));
我们将迭代值作为函数变量传递给IEF。这样,它通过闭包传递给处理程序。值得reading up on these。
答案 1 :(得分:2)
另一种方法是使用ECMAScript 2015中的let。
for(let i=0; i < forms.length; i++) {
forms[i].addEventListener('change', function(){
checkAllFilled(i);
});
}
答案 2 :(得分:1)
您总是调用最后生成的事件侦听器,因为您首先生成这些侦听器(都具有相同的名称),然后调用它们中的最后一个。
此处的最佳解决方案是根据计数器值i为
指定处理事件的函数的名称答案 3 :(得分:1)
使用forEach()
代替for
循环:
var forms = document.getElementsByTagName('form');
[].slice.call(forms).forEach(function(form, i) {
form.addEventListener('change', function(){
checkAllFilled(i);
});
});