jQuery - why can't I bind events to elements in a loop?

断了今生、忘了曾经 提交于 2019-12-13 03:36:16

问题


Here is my code:

  var b = $(slipStream.conf.mainVis).find('p#prev');
  b.click(function() {
    slipStream.slideLeft();
        return false;
  });

  b = $(slipStream.conf.mainVis).find('p#next');
  b.click(function() {
    slipStream.slideRight();
        return false;
  });

  b = $(slipStream.conf.controls).find('li img');
  console.log(b);
  for (var l in b) {
        l.click(function() {
              var visIndex = l.index();
              console.log(visIndex);
        });
  };

The first two bindings go through, no problem. But I can't loop through a collection and bind something to each member? (the console is telling me that "l.click is not a function.") Is this a limitation of jQuery or is my code off? This seems like it would be the way to do it, though...


回答1:


When you enumerate over a jQuery object, the values being enumerated are actual DOM nodes and not jQuery wrappers. Therefore, they don't have a click method but you can wrap them again to get all the usual functionality.

Of course this is not necessary because you can simply attach a wrapper directly from your initial jQuery instance:

$(slipStream.conf.controls).find('li img').click(function() {
    var visIndex = $(this).index();
    console.log(visIndex);
});



回答2:


This is the classic "loop variables don't work properly in callbacks" bug.

Your variable l no longer has the originally supplied value by the time the callback is invoked - it has whatever final value was assigned in the last pass through the loop.

[FWIW, l isn't actually a jQuery object, so you have to wrap it - $(l) to use it with jQuery]

The usual fix to the loop bug is to create an additional closure that returns a function bound to the current value:

for (var l in b) {   // NB: don't use `for ... in ...` on array-like objects!
    var make_cb = function(n) {
         return function() {
              var visIndex = $(n).index();
              console.log(visIndex);
         }
    }
    $(l).click(make_cb(l));
};

Fortunately, you don't need a loop at all - you can have jQuery automatically add the callback to every element by itself:

b = $(slipStream.conf.controls).find('li img');
b.click(function() {
    var visIndex = $(this).index();
    console.log(visIndex);
});



回答3:


Could it be that the problem is the forloop. .click is part of the jQuery, so you must be sure that it's called on element that is wrapper with jQuery.

$.each(b, function (index, element) {
   $(element).click(function() {
   });
};



回答4:


With each() you can iterate through a set of jQuery objects:

$(slipStream.conf.controls).find('li img').each(function(){
    $(this).click(function() {
        var visIndex = $(this).index();
        console.log(visIndex);
    });
});

$(this) will match the currently indexed object from the collection.



来源:https://stackoverflow.com/questions/9583072/jquery-why-cant-i-bind-events-to-elements-in-a-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!