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

Assign click handlers in for loop

提问人:Philip 提问时间:11/4/2010 最后编辑:givansePhilip 更新时间:10/13/2017 访问量:60443

问:

我有几个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'

JavaScript jQuery jQuery-selectors 闭包

评论


答:

140赞 Harmen 11/4/2010 #1

在 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,你可以使用这个关键字,它使变量成为循环的局部变量,而不是全局变量:leti

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

它更短,更容易理解。

评论

7赞 hurikhan77 11/8/2010
实际上,作为解释,应该写成引用“i”的匿名函数仅在循环的上下文中执行,而不是立即运行。这意味着,当 onclick 事件发生时,“i”实际上处于循环的结束条件。您可以通过将“i”作为本地参数传递来规避此问题(就像此回调解决方案一样)。
3赞 T.J. Crowder 1/16/2012
我真的不会叫“回调”。这不是回调。这是一个用于创建回调的工厂。callback
0赞 Ian 8/7/2013
非常有用的答案。也有这个问题,并且能够修改您的解决方案以在每次循环通过时创建绑定单击事件。
0赞 de_nuit 10/29/2014
它永远是二十。由客户端增量引起。
12赞 Donald 11/4/2010 #2

澄清一下,i 等于 20,因为点击事件直到循环结束后才会触发。

2赞 stancoffyn 11/4/2010 #3

通常,如果您希望将单击句柄分配给大量项目,则需要一个容器(更高级别的 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>
4赞 PleaseStand 11/4/2010 #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 方法去除首字母。

注意:使用可能会更好

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

而不是

$('.mydivs').click(function(){
7赞 user1490857 6/5/2013 #5
$(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);
  }
});

评论

0赞 Vad 10/13/2016
通过匿名功能对我来说效果更好
6赞 Ricardo de Assuncao Goncalves 11/3/2015 #6

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

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

//
// 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);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>