在for循环中分配点击处理程序


74

我有几个div的#mydiv1#mydiv2#mydiv3,...和要指派点击处理对他们说:

$(document).ready(function(){
  for(var i = 0; i < 20; i++) {
    $('#question' + i).click( function(){
      alert('you clicked ' + i);
    });
  }
});

但是,我没有得到单击'you clicked 3'时的显示#mydiv3(就像其他所有单击一样)'you clicked 20'。我究竟做错了什么?

Answers:


135

在Javascript中的循环中创建闭包是一个常见的错误。您需要具有以下某种回调函数:

function createCallback( i ){
  return function(){
    alert('you clicked' + i);
  }
}

$(document).ready(function(){
  for(var i = 0; i < 20; i++) {
    $('#question' + i).click( createCallback( i ) );
  }
});

2016年6月3日更新:由于这个问题仍然受到关注,ES6也越来越受欢迎,因此,我建议使用一种现代的解决方案。如果您编写ES6,则可以使用let关键字,该关键字使i变量在循环本地而不是全局:

for(let i = 0; i < 20; i++) {
  $('#question' + i).click( function(){
    alert('you clicked ' + i);
  });
}

它更短,更容易理解。


7
实际上,作为解释,应该写成引用“ i”的匿名函数仅在没有立即运行的循环的上下文中执行。这意味着,当发生onclick事件时,“ i”实际上处于循环的结束条件。您可以通过传递“ i”作为本地参数来规避此问题(如此回调解决方案那样)。
hurikhan77

3
真的不会叫callback“回调”。这不是回调。这是创建回调的工厂。
TJ Crowder 2012年

确实有用的答案。同样也存在此问题,并且每次循环通过时都能够修改您的解决方案以创建绑定单击事件。
2013年

永远是二十。由客户端增量引起。
de_nuit 2014年

12

需要说明的是,我等于20,因为直到循环完成后,才触发click事件。


7
$(document).ready(function(){
  for(var i = 0; i < 5; i++) {
   var $li= $('<li>' + i +'</li>');
      (function(i) {
           $li.click( function(){
           alert('you clicked ' + i);
         });
      }(i));
      $('#ul').append($li);
  }
});

对我来说,通过匿名函数传递效果更好
Vad

6

使用on附加“ click”处理程序,您可以使用事件数据来传递数据,如下所示:

for(var i = 0; i < 20; i++) {
  $('#question' + i).on('click', {'idx': i}, function(e) {
    alert('you clicked ' + e.data.idx);
  });
}


4

您可以一次分配单击处理程序(或者至少不进行许多不必要的关闭)。将所有div放在一个类中mydivs,然后:

$(document).ready(function(){
    $('.mydivs').click(function(){
        // Get the number starting from the ID's 6th character
        // This assumes that the common prefix is "mydiv"
        var i = Number(this.id.slice(5));

        alert('you clicked ' + i);
    });
});

这使用slice字符串方法将元素的开头字母去除,从而查看元素的ID以获取其编号。

注意:使用可能会更好

$('#divcontainer').on('click', '.mydivs', function(){

代替

$('.mydivs').click(function(){

2

通常,如果您希望为大量项目分配点击处理,则您希望有一个容器(较高的div级别)来为您解释点击,因为点击会从dom中冒出来。

<div id="bucket">
    <span class="decorator-class" value="3">
    ...
</div>

<script>
   $(document).ready(function(e){
      $("#bucket").live('click', function(){
         if(e.target).is('span'){
            alert("elementid: " + $(e.target).val());
         }
      }
   }
<script>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.