使用循环在事件侦听器上传递参数

时间:2011-08-06 16:28:10

标签: javascript html events prototypejs

只是一个简单的问题,任何人都可以告诉我为什么这不起作用以及如何解决它?本质上,它采用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的值总是循环中的最后一项,这不是我想要的那样,因为我希望它们是循环那个阶段的当前值。我意识到我错过了一些非常简单但却无法解决的问题!

4 个答案:

答案 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));
}

根据rowstr的不同,您甚至可能不需要循环索引。也许你可以通过另一种方式获取事件处理程序中的元素索引。例如。如果trHTMLTableRowElement [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被设置为最后一行。