2012-05-06 16 views
11

Setup:jQuery funkcja jest wywoływana dwukrotnie za każde kliknięcie

napisałem funkcję jQuery, aby zaktualizować komórki tabeli z table_2, gdy wiersz w table_1 kliknięciu. Oto co napisałem:

<script type="text/javascript"> 
     $("tr").live('click',function() { 
      var host = $(this); 
      alert('A row in table 1 is clicked!'); 

      var count = host.find("td").eq(2).text(); 
      $("#myTable_2 tr:eq(0) td:eq(1)").text(count); 
      $("#myTable_2 tr:eq(1) td:eq(1)").text(5); 
     }); 
    </script> 

Problem:

Kiedy krok za pośrednictwem tej funkcji za pomocą FireBug, widzę danych komórek w myTable_2 jest zmieniany. ALE, za każde kliknięcie, funkcja jest wykonywana dwukrotnie. Widzę pole alertu pojawiające się dwukrotnie dla każdego kliknięcia.

Czy ktoś może mi powiedzieć, dlaczego tak się dzieje? I jak tego uniknąć?

Odpowiedz

11

jedną z następujących czynności:

  1. się wybrane rząd jest wewnątrz innego rzędu (dwa rzędy kliknięcia). (example)
  2. Wyświetlany kod jest wykonywany dwukrotnie (example).

Aby rozwiązać ten problem, wybierz bardziej precyzyjny selektor. Jeśli używasz jQuery 1.7+ używać .on zamiast live: http://jsfiddle.net/6UmpY/3/

$(document).on("click", "#myTable_1 > tbody > tr", function() { 
    // This selector will only match direct rows of the myTable_1 table 

Uwaga: Używanie .on zamiast live nie rozwiąże problemu.
Użycie bardziej szczegółowego selektora spowodowało naprawienie problemu.
Jeśli kochasz live dodaje również pracować: http://jsfiddle.net/6UmpY/4/

$("#myTable_1 > tbody > tr").live("click", function() { 
3

zakładać table_1 jest id z pierwszej tabeli.

$("#table_1 tbody").on('click','tr', function() { 
      var host = $(this); 
      alert('A row in table 1 is clicked!'); 

      var count = host.find("td").eq(2).text(); 
      $("#myTable_2 tr:eq(0) td:eq(1)").text(count); 
      $("#myTable_2 tr:eq(1) td:eq(1)").text(5); 
     }); 

UWAGA:live() została zaniechana, więc pisać jak powyżej. kod jest wykonywany dwa razy, ponieważ selektor tr należy do obu tabel i powiązania zdarzeń dwa razy.

Można również użyć delegate():

$("#table_1 tbody").delegate("tr", "click", function(){ 
    var host = $(this); 
    alert('A row in table 1 is clicked!'); 
    var count = host.find("td").eq(2).text(); 
    $("#myTable_2 tr:eq(0) td:eq(1)").text(count); 
    $("#myTable_2 tr:eq(1) td:eq(1)").text(5); 
}); 
+0

Dzięki za odpowiedź. Masz na myśli, że użycie polecenia "on" lub "delegate" rozwiąże problem wywoływania funkcji dwa razy? – Bhushan

+0

@Learner no 'on()' jest używany do wiązania zdarzenia z jquery 1.7+, a dwa razy eventowy ogień zostanie rozwiązany za pomocą '# table_1', ponieważ wybierze tylko' tr', które należy do pierwszej tabeli – thecodeparadox

+0

dzięki theododaradox. – Bhushan

12

po prostu uniknąć szerzenia się kliknięciem

$("tr").live('click',function() { 

     ... 

     $(event.toElement).one('click', function(e){ e.stopImmediatePropagation(); }); 
    }); 
+0

Czy są jakieś potencjalne negatywne konsekwencje takiego postępowania? –

+1

To zatrzyma cokolwiek innego, słuchającego zdarzenia na elemencie odbierającym wydarzenie. Zdarzenia są wywoływane w kolejności, w jakiej są dodawane, a tylko wydarzenia dodane po tym zostaną zablokowane. – neopickaze

0

To dlatego $ ("tr") Live ('click', funkcji.() {}); ^^^^^ ma 2 liczenia w html. Aby upewnić się, że .live() lub .delegate() jest wykonywane raz, selektor w $ (selector) .delegate() lepiej jest "$ (table [name = users])" niż $ ("td") lub $ ('tr')

0

Niektóre elementy mogą mieć takie same właściwości (nazwa klasy, nazwa znacznika itp.), które możesz przeoczyć. To może spowodować taki konflikt. W poniższym przykładzie element "tr" jest używany jako selektor dla alertu, ale skrypt ma dwa zagnieżdżone elementy "tr", które zawierają cel "tekst".W ten sposób za pomocą jednego kliknięcia otrzymujesz alert wystrzeliwany osobno dla każdego (od środka) elementu "tr". Nazywa się to bubbling. Możesz po prostu użyć stopPropogation(), aby zatrzymać bubbling.

$("tr").live('click',function() { 
    alert('A row in table 1 is clicked!'); 
    event.stopPropogation(); 
}); 

<table> 
    **<tr>** 
    <td>  
     <table id="myTable_1"> 
     **<tr>** 
     <td>Test</td> 
     **</tr>** 
     </table> 
    </td> 
    **</tr>** 
</table> 

http://jsfiddle.net/6UmpY/97/

Powiązane problemy