2010-06-27 49 views
5

有人能告诉我为什么这个代码:jQuery的,单击事件,太多的递归调用

$('#places-view > tbody').find('td').click(function(evt) { 
    var td = $(this), 
     input = td.find('input'); 
     console.log('click'); 
     console.log(input.attr('disabled'), 'disabled'); 
     if (! input.attr('disabled')) { 
      input.trigger('click'); 
      console.log('inner click'); 
     } 
}) 

扔太多的递归调用错误...

问候

回答

1

当你触发了“点击” ,它不是一个单独的事件调度循环— jQuery将在那里运行处理程序。由于你的<input>里面的你的<td>,这个事件会冒泡到<td>本身,在那里它会再次运行到那个处理程序。

另外请注意,这条线的位置:

console.log(input.attr('disabled'), 'disabled'); 

是也许不是你想要的 - 我认为会随时登录这个词“已禁用”。也许你的意思

console.log(input.attr('disabled') + ' disabled'); 
+0

我使用萤火虫控制台,所以在我的情况下,所有的预期工作。 – Marek 2010-06-27 15:34:11

6

为了防止事件冒泡,放置在处理器event.stopPropagation()input元素的click事件。

$('#places-view input').click(function(event) { 

     // This will prevent the click event from bubbling up and firing 
     // the click event on your <td> 
    event.stopPropagation(); 

     // run the rest of your click code 
}); 

http://api.jquery.com/event.stopPropagation/


编辑:作为@Pointy指出,这可能是你的意图具有相同的处理程序处理这两种事件,或至少有td处理器依然火的时候,你点击input

如果是这样的话,你只需要检查,看看是否td处理程序通过点击在input解雇,如果是这样,防止input.trigger("click")运行:

​​

另一种方式做测试将是:

if(input[0] != evt.target) {... 

这两种方法假定这里有一个input。如果情况并非如此,那么您需要为输入提供一个标识符以使测试更加具体。

+0

这是真的,但我不得不怀疑这是否是一个好主意。如果他确实想在'​​'级别处理“点击”,那么取消在''处的冒泡可能是不好的,因为这会将点击分流到'​​'。当然,这取决于表格单元格中的其他内容。 – Pointy 2010-06-27 14:09:40

+0

@Pointy - 你说得对。我的假设是'td'的点击发生在'td'的其他地方,因此,处理程序将是分开的。如果不是这种情况,那么OP可能需要测试'td'处理程序中的'evt.target'来查看点击是否在'input'上,如果是,绕过触发'click()' '输入'。 – user113716 2010-06-27 14:43:30

+0

很好的答案,+1 – Mark 2010-06-27 15:10:30