jQuery函数每次点击会被调用两次。

11

设置:

我写了一个jQuery函数,当点击table_1的一行时,可以更新table_2的表格单元格。以下是我的代码:

    <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中的单元格数据正在被更改。但是,每次点击时,函数都会被执行两次。我可以看到每次点击时警示框都会出现两次。

有人能告诉我为什么会发生这种情况吗?如何避免这种情况?

5个回答

12

只需简单地避免点击的传播即可

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

        ...

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

这样做有没有潜在的负面影响? - Dan Eastwell
1
这将阻止任何其他监听事件在接收事件的元素上被触发。事件按照它们被添加的顺序调用,只有在此之后添加的事件将被阻止。 - neopickaze

11

可能是以下两种情况之一:

  1. 点击的行位于另一行内(即点击了两行)。 (示例)
  2. 你展示的代码被执行了两次 (示例).

要解决这个问题,请使选择器更加具体。如果您正在使用 jQuery 1.7+,请使用.on代替livehttp://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() {

3

假设table_1是第一个表的id。

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

谢谢回复。那么你的意思是使用 'on' 或者 delegate 将解决函数被调用两次的问题? - Bhushan
@Learner,从jQuery 1.7+开始不再使用on()来绑定事件,而且可以通过使用#table_1解决两次事件触发的问题,因为它只会选择属于第一个表格的tr - thecodeparadox

0

有些元素可能具有相同的属性(类名、标签名称等),这可能会被忽略,从而引起冲突。在下面的示例中,“tr”元素被用作警报的选择器,但脚本包含了两个嵌套的“tr”元素,这些元素包含了“text”目标。因此,只需单击一次,就会分别触发每个(由内向外)“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/


0

这是因为在HTML中,$("tr").live('click',function() {});出现了两次。 为确保.live()或.delegate()只执行一次,$(selector).delegate()中的选择器最好是"$(table[name=users])",而不是$('td')或$('tr')。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接