2010-06-27 29 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