17

我尝试使用 for 创建一个循环,并通过 onclick 事件递增,但它不起作用。

js的一部分:

 var gameCase = ['', '', '', '', '', '', '', '', ''], // 9
    itemLists = $('game').getElementsByTagName('li'); // 9 items

    for( var i = 0; i < itemLists.length; i++ ) {
         // i already egal to 9
         itemLists[i].onclick = function() {
              // do something
         }
    }

但在这种情况下,在我能够单击列表的元素之前,For 循环已经完成。

此外,我想获取我单击的项目列表并将其保存在数组中。我尝试了一个 gameCase[this] (在 onclick 函数中),但我不知道这是否是好方法。

4

4 回答 4

29

John Resig 在“JavaScript Ninja 的秘密”( http://ejohn.org/apps/learn/#59)中很好地介绍了这个主题

您需要创建一个临时范围来保留 i 的价值

for ( var i = 0; i < itemLists.length; i++ ) (function(i){ 
  itemLists[i].onclick = function() {
      // do something
  }
})(i);

编辑:

var gameCase = ['', '', '', '', '', '', '', '', ''], // 9
$listParent = $('game').find('ul'), // li's parent
itemLists = $('game').getElementsByTagName('li'); // 9 items

var listHandler = (function() {
  var i = 0;

  return function() {
    // $(this) will in here refer to the clicked li
    i++ // increment i

    if ( i === 9 ) {
      $listParent.off('click', 'li', listHandler); //remove eventhandler when i reaches 9
    }
  }
}());

$listParent.on('click', 'li', listHandler); // attach eventhandler to ul element

这应该做你想要的,因为我在工作,所以现在不能测试它。

于 2013-04-07T09:12:52.030 回答
11

包装你的听众:

onclick = (function(i) {return function() {
    ...
};})(i);

这解决了您的变量范围问题。

于 2013-04-07T09:09:58.177 回答
1

抱歉,如果我没有正确理解您的问题,从代码中我了解到,您正在尝试将 onclick 处理程序添加到游戏标签中找到的所有列表元素(也许它应该是一个类/ID)。

当脚本标签/文件在没有任何用户交互的情况下加载时,将执行 for 循环。

如果您希望分配一个使用计数器当前值的函数。使用以下代码:

itemLists[i].onclick = (function() {
    return function() {
         // TODO ---
        // Your handler code here
}
})();
于 2013-04-07T09:13:03.317 回答
1

另一种选择是使用 forEach 循环,这会为每次迭代创建一个新变量。

var gameCase = ['', '', '', '', '', '', '', '', ''], // 9
itemLists = $('game').getElementsByTagName('li'); // 9 items

itemLists.forEach(function(item,index){
    item.onclick = function() {
      // do something
 }
});
于 2019-04-19T23:32:21.263 回答