Функция jQuery вызывается дважды для каждого щелчка

Настройка:

Я написал функцию jQuery для обновления ячеек таблицы таблицы_2, когда нажата строка в таблице_1. Вот что я написал:

    <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>

Проблема:

Когда я перехожу через эту функцию с помощью FireBug, я вижу, что данные ячейки в myTable_2 меняются. НО, для каждого щелчка функция выполняется дважды. Я вижу окно предупреждения, появляющееся дважды для каждого щелчка.

Может кто-нибудь сказать мне, почему это происходит? И как этого избежать?

Ответ 1

Любое из следующего:

  • Выбранная строка находится внутри другой строки (нажаты две строки). (пример)
  • Код, который вы показали, выполняется дважды (пример).

Чтобы решить эту проблему, сделайте свой селектор более конкретным. Если вы используете jQuery 1.7+, используйте .on вместо 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

Примечание. Использование .on вместо live не решило проблему.
Использование более конкретного селектора действительно устранило проблему.
Если вы любите live, также будет работать следующее: http://jsfiddle.net/6UmpY/4/

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

Ответ 2

просто избегайте распространения щелчка

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

        ...

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

Ответ 3

Предположим, что table_1 является идентификатором первой таблицы.

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

ПРИМЕЧАНИЕ. live() устарел, поэтому напишите, как указано выше. вы выполняете код дважды, потому что селектор tr принадлежит к двум таблицам и привязке события дважды.

Вы также можете использовать 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);
});

Ответ 4

Это потому, что  $ ( "tr" ). live ('click', function() {});  ^^^^^ имеет 2 счета в html. Чтобы обеспечить выполнение .live() или .delegate() один раз, селектор в $(selector).delegate() лучше быть "$ (table [name = users])", а не $('td') или $( 'тр')

Ответ 5

Некоторые элементы могут иметь одинаковые свойства (имя класса, имя тега и т.д.), которые вы можете игнорировать. Это может вызвать такой конфликт. В приведенном ниже примере элемент "tr" используется как селектор для предупреждения, но script имеет два вложенных элемента "tr" , которые содержат цель "текст". Таким образом, одним щелчком мыши вы получаете предупреждение для каждого (изнутри наружу) элемента "tr" отдельно. Это называется bubbling. Вы можете просто использовать stopPropogation(), чтобы остановить 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/