只是一个简单的问题,任何人都可以告诉我为什么这不起作用以及如何解决它?本质上,它采用HTML中的一组表行并动态地将点击事件附加到它们。
for (var a=index; a<rows.length; a++) {
tr = rows[a];
tr.onclick = function() { DropDownManager.onItemClick(tr, a); };
tr.observe("click", function() { DropDownManager.onItemClick(tr, a); });
}
这段代码的问题在于传递给DropDownManager.onItemClick的值总是循环中的最后一项,这不是我想要的那样,因为我希望它们是循环那个阶段的当前值。我意识到我错过了一些非常简单但却无法解决的问题!
答案 0 :(得分:14)
JavaScript没有块范围,因此例如循环不会创建新范围。您可以使用以下函数创建一个:
for (var a=index; a<rows.length; a++) {
(function(a) {
tr = rows[a];
tr.onclick = function() { DropDownManager.onItemClick(this, a); };
tr.observe("click", function() { DropDownManager.onItemClick(this, a); });
}(a));
}
根据rows
和tr
的不同,您甚至可能不需要循环索引。也许你可以通过另一种方式获取事件处理程序中的元素索引。例如。如果tr
是HTMLTableRowElement
[MDN],那么您可以通过this.rowIndex
在其他行中获得其位置。
顺便说一下。你为什么两次绑定相同的事件处理程序?
答案 1 :(得分:4)
除了在循环中存储DOM对象的属性之外,您还可以使用函数闭包来“冻结”循环中变量的副本以用于特定函数调用。你可以这样做:
for (var a=index; a<rows.length; a++) {
tr = rows[a];
tr.onclick = function(tr, a) {
return(function() {
DropDownManager.onItemClick(tr, a);
});
}(tr,a);
}
这样做是为了分配tr.onclick执行匿名函数调用的结果,该函数调用将两个变量作为参数(名为tr和a)并传递tr和a的当前值作为参数(此传递当前值“冻结”此函数闭包内的那些变量的当前值。
执行该函数调用的结果本身就是另一个匿名函数。因为这个内部匿名函数现在被赋值给tr.onclick,所以它创建了一个函数闭包,它保持当前在该闭包中的所有状态。该状态包括tr和a的“冻结”值,但它们仅保留在此函数闭包内部,因此每次循环都会创建一个新的函数闭包,其中包含tr和a的新“冻结”和“存储”值。
答案 2 :(得分:0)
部分是因为我很迂腐,部分原因是因为这是可能的,所以这是完全相同的事情。
Event.on('table_id', 'click', 'tr', function(event, tr) {
DropDownManager.onItemClick(tr, rows.indexOf(tr));
});
请注意,要冒泡的事件需要包含表,它由ID标识,但您也可以直接传递元素。
答案 3 :(得分:-1)
for (var a=index; a<rows.length; a++) {
tr = rows[a];
tr.setAttribute('a', a);
tr.onclick = function() { DropDownManager.onItemClick(this, this.getAttribute('a')); };
tr.observe("click", function() { DropDownManager.onItemClick(this, this.getAttribute('a')); });
}
尝试这种方式。
它将传递tr,因为变量tr被设置为最后一行。