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

时间:2010-11-03 21:15:04

标签: javascript jquery jquery-selectors closures

我有几个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'。我做错了什么?

6 个答案:

答案 0 :(得分:126)

在Javascript中创建closures in loops是一个常见的错误。你需要有这样的回调函数:

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

它更短,更容易理解。

答案 1 :(得分:12)

为了澄清,我等于20,因为在循环结束之前,click事件才会被触发。

答案 2 :(得分: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);
  }
});

答案 3 :(得分: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);
    });
});

这会查看元素的ID以获取其编号,使用slice string method删除首字母。

注意:最好使用

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

而不是

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

答案 4 :(得分:3)

使用on附加&#39;点击&#39;处理程序,您可以使用事件数据,以传递您的数据,如:

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

&#13;
&#13;
//
// let's creat 20 buttons
//

for(var j = 0; j < 20; j++) {
	$('body').append($('<button/>', {type: 'button', id: 'question' + j, text: 'Click Me ' + j}))
}

//
// Passing data to the handler
//
for(var i = 0; i < 20; i++) {
  $('#question' + i).on('click', {'idx': i}, function(e) {
    console.log('you clicked ' + e.data.idx);
  });
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

答案 5 :(得分: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>