2015-01-15 169 views
1

這將是一個很難解釋...jQuery .on()不能正常工作

我有一個按鈕是一個自定義的按鈕。

<button class="like-post">Like Post</button> 

用戶點擊等之後,我做一個AJAX調用,並添加一行到數據庫,然後添加和刪除類。

btn.removeClass('btn-success') 
      .removeClass("like-post") 
      .addClass('btn-default') 
      .addClass('unlike-post') 
      .html("<span class='glyphicon glyphicon-remove'></span> Un-like"); 

這是所有工作正常,除非班級改爲'不同的職位'後按鈕仍然反應類似職位類觸發器。

所以我有這樣的:

$(".like-post").on('click', function(){ }); 

,其執行後連按鈕沒有類樣後的這一行動。我已經檢查過,班級肯定會被刪除/正確添加。

我想用不同的帖子類進行另一個動作,但不能解決這個問題。

我注意到我的網站上有關.on()的其他類似問題。我無法在jsFiddle中重新創建問題,因爲它在那裏可以正常工作。

使用bootstrap +最新的jQuery版本。有任何想法嗎?我知道它很長一段時間,但認爲有人可能會遇到類似的問題。

謝謝。

+0

你可能需要.unbind( )'.like-post'類並綁定新的'.unlike-post',反之亦然。我敢打賭,原始類仍被DOM用作參考。 – below9k

回答

6

問題是你連接一個處理程序到元素,之後它不會影響類是否改變。

使用連接到非改變的祖先委託的處理程序:

$(document).on("click", ".like-post", function(){ }); 

委託的事件通過偵聽事件冒泡祖代元素工作。然後,他們在事件時間(而不是事件註冊時間)將jQuery過濾器應用到泡沫鏈中的元素。然後,他們僅將該功能應用於導致該事件的匹配元素。這種類型的處理程序實際上可以更有效率(因爲它交換速度較慢的事件處理程序的速度要快得多)。由於點擊速度非常慢,您永遠不會注意到委託事件處理程序比直接連接的處理程序要慢。

文檔is the default if no other element is handy, but never use body`因爲它有一個錯誤(如果樣式導致計算出的身高0,它不會響應鼠標事件)。

通常雖然你會嘗試綁定到不斷變化的元素附近的祖先。

+2

我不知道「身體」的錯誤。你能鏈接到更多的信息? – Octopus

+0

@Octopus:自己發現它。用絕對位置的子元素創建頁面(計算出的身高爲0)。鼠標點擊事件停止冒泡到正文。另一方面文件總是得到事件,所以是一個更好的默認值(只有一步從身體刪除) –

+0

感謝這個優秀的答案!沒有意識到我並沒有像我想象的那樣使用。 – Lovelock

0

這是因爲.on()在一個特定時刻評估元素,當它被定義時。它與選擇器是否匹配並不重要。此刻將匹配與like-post

$("body").on("click", ".like-post", function() {}); 

這樣,只有元素:

如果你需要更靈活的解決方案,更多參數傳遞給.on(),像這樣。

它不需要是body,它可以是您知道的最深的元素將始終包含此.like-post按鈕。

+0

從不使用'body'作爲委託事件的默認值,因爲它有一個錯誤(如果樣式導致計算的身高爲0,它不會響應鼠標事件)。爲了以防萬一,請使用'document'作爲後備*。 –

1

我想這個問題依賴於on的定義。 (請參閱http://api.jquery.com/on/

實際上有兩種「on」工作方式。

$(".like-post").on("click", function() { 
}); 

$("body").on("click", ".like-post", function() { 
}); 

第一基本上意味着:

綁定在具有「生命郵報」目前的類時,點擊執行情況的所有元素的功能。

第二個是:當點擊事件發生在具有「like-post」類的元素的「body」內時,執行該函數。

主要區別在於,第一次執行代碼(意味着綁定代碼)時,第一個綁定在元素的「當前狀態」上,而第二種情況反映了「click」操作時dom元素的狀態發生。

您可以使用$(document)或其他選擇器來代替body,但基本上你必須避免直接使用該元素,而應該使用它的父級。

或者你也可以像一張支票:

$(".like-post").on("click", function() { 
    // the class has been removed 
    if(!$(this).hasClass("like-post)) 
     return; 

    ...... 
}); 
+0

從不使用'body'作爲委託事件的默認值,因爲它具有錯誤(如果樣式導致計算的身高爲0,則它​​不會響應鼠標事件)。使用'document'作爲後備。 –

1

當你直接添加事件的元素,它不會奇蹟般地當您更改類中刪除該事件。您可能需要解除綁定或在函數內添加邏輯。另一種選擇是使用事件委派

取消綁定,例如:

$(".like-post").on('click', function(){ 
    var btn = $(this); 
    if (btn.hasClass("xxx")) { 
     //do this logic 
    } else { 
     //do that logic 
    } 
}); 

事件委派:

$(".like-post").on('click', function(){ 
    $(this).unbind("click"); 
    //logic here 
}); 

用支票基本思路

$(document).on("click", ".like-post", function(){ console.log("like clicked" });