72 votes

Affecter des gestionnaires de clics dans la boucle for

J'ai plusieurs div's #mydiv1 , #mydiv2 , #mydiv3 , ..., et je souhaite leur affecter des gestionnaires de clics:

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

Mais au lieu d'afficher 'you clicked 3' lorsque vous cliquez sur #mydiv3 (comme pour tous les autres clics), j'obtiens 'you clicked 20' . Qu'est-ce que je fais mal?

131voto

Harmen Points 11632

C'est une erreur courante de créer des fermetures dans des boucles en Javascript. Vous devez avoir une sorte de fonction de rappel comme ceci:

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

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

12voto

Donald Points 926

Pour clarifier, i est égal à 20 car l'événement click n'aura pas été déclenché avant la fin de la boucle.

7voto

user1490857 Points 1
$(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);
  }
});

4voto

PleaseStand Points 16718

Vous pouvez vous en tirer avec l'attribution du gestionnaire de clic une fois (ou au moins ne pas faire bien des fermetures). Mettre tous les divs dans une classe mydivs, alors:

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

Cela ressemble à l'identification de l'élément pour obtenir son numéro, à l'aide de l' slice chaîne de la méthode de la bande de la lettre initiale off.

Remarque: Il peut être préférable d'utiliser

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

au lieu de

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

2voto

stancoffyn Points 31

En règle générale, si vous souhaitez affecter des poignées de clic à un grand nombre d'éléments, vous souhaitez créer un conteneur (div de niveau supérieur) qui interprète les clics pour vous, sous forme de bulles de clichés du 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>
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X