2014-06-15 51 views
0

我的頁面上有一個菜單。在每個菜單項的點擊它調用的以下功能之一:JQuery函數在屬性更改後仍然運行

$('.sideNav1').click(function(){ 
    $('.sideNav1').attr('class','selected1'); 
    $('.selected2').attr('class','sideNav2'); 
    $('.selected3').attr('class','sideNav3'); 
    alert("1 selected"); 
    return false; 
}); 

$('.sideNav2').click(function(){ 
    $('.sideNav2').attr('class','selected2'); 
    $('.selected1').attr('class','sideNav1'); 
    $('.selected3').attr('class','sideNav3'); 
    alert("2 selected"); 
    return false; 
}); 

$('.sideNav3').click(function(){ 
    $('.sideNav3').attr('class','selected3'); 
    $('.selected2').attr('class','sideNav2'); 
    $('.selected1').attr('class','sideNav1'); 
    alert("3 selected"); 
    return false; 
}); 

HTML:

<div class="sideNav1"> 
Nav 1 
</div> 
<div class="sideNav2"> 
Nav 2 
</div> 
<div class="sideNav3"> 
Nav 3 
</div> 

繼屬性的變化(其中,根據在Chrome瀏覽器開發工具,確實發生了)我想期望選定的div在點擊時不做任何事情。相反,它表現得好像沒有屬性更改,並且click()事件偵聽器仍然要求.sideNav...再次運行該函數。

有什麼我可能會在這裏失蹤?

回答

3

jQuery靜態事件處理程序(您正在使用的類型)在第一次運行代碼時綁定事件處理程序ONCE。之後對類名的任何修改都不重要,並且不會以任何方式影響事件處理程序。

對於傳播的事件,您可以使用委派的事件處理來評估每個事件的選擇器匹配。在委託事件處理中,您將事件綁定到一個靜態父對象(在您安裝事件處理程序時其DOM元素存在並且在任何時候不會重新創建的對象),並且您使用.on()的委託形式。

在你的情況,你必須選擇一個靜態家長的選擇和使用是這樣的:

$(some parent selector).on("click", ".sideNav1", function() {...}); 

雖然它是可取的(在大頁面性能原因)使用比一個更接近父<body>元素,你甚至可以做到這一點:

$(document.body).on("click", ".sideNav1", function() {...}); 

然後,事件處理程序將只在目標對象具有.sideNav1類的名字,當它不叫沒有。

的方式委託事件處理工作正是如此:

  1. 像「點擊」事件有些事件傳播父級鏈。在目標對象上調用它們之後,將調用鏈上的所有父對象直到document對象或直到有人調用.stopPropagation()

  2. 因此,如果您爲父對象上的特定事件安裝事件處理程序,則可以看到子節點上發生的所有事件(假設沒有人在其上調用.stopPropagation())。

  3. 使用.on()的委託形式jQuery將檢查父對象上調用的每個事件,以查看匹配第二個選擇器傳遞的事件的原始目標,並檢查事件發生時的運行時。由於此檢查在事件分發時是實時的,因此您將對DOM元素進行任何動態更改(如您的情況)。

你可以閱讀更多有關使用委託的事件,在這些文獻處理:

jQuery .live() vs .on() method for adding a click event after loading dynamic html

jQuery selector doesn't update after dynamically adding new elements

jQuery .on does not work but .live does

Does jQuery.on() work for elements that are added after the event handler is created?

JQuery Event Handlers - What's the "Best" method

這些答案中最常見的情況是在安裝事件處理程序後添加或重新創建的DOM元素,但問題與修改其上的類的DOM元素幾乎相同,期望事件處理程序改變他們的行爲。


僅供參考,我還普遍建議你使用.addClass().removeClass(),而不是爲.attr(),讓你的程序的其他部分來對這些對象(造型或其他原因)使用其他類。

+0

感謝您早日respnse!要使用您的方法,我是否必須將HTML更改爲'

Nav 1
'? – Wildcard27

+0

@ matt1985 - 您可以使用任何常見的父母。它不一定是直接的父母。你並不知道你的HTML如何,但如果你有任何常見的容器div,你可以使用它 - 你不一定要添加一個新的容器對象。你甚至可以使用'body'對象作爲公共父對象,儘管越接近父對象,你就可以選擇更好的性能(只有當你有很多委託事件處理程序連接到同一個對象時,性能纔會有所不同相同的頁面)。 – jfriend00

+0

非常感謝您提供解決方案,但深入的解釋。我看到147k代表來自哪裏:) – Wildcard27

0

如果添加sideNav類所有的div,你可以做這樣的事情:

$('.sideNav').click(function(){ 
    $('.sideNav').removeClass("selected"); 
    $(this).addClass("selected"); 

}); 

的jsfiddle例如:http://jsfiddle.net/Tec3D/

-1

OK,我從活到...

改變
$(document).on('click','.sideNav1',function(){ 
    $(this).unbind('click').attr('class','selected1'); 
    $('.selected2').attr('class','sideNav2').bind('click'); 
    $('.selected3').attr('class','sideNav3').bind('click'); 
    alert("1 selected"); 
    return false; 
}); 

$(document).on('click','.sideNav2',function(){ 
    $(this).unbind('click').attr('class','selected2'); 
    $('.selected1').attr('class','sideNav1').bind('click'); 
    $('.selected3').attr('class','sideNav3').bind('click'); 
    alert("2 selected"); 
    return false; 
}); 

$(document).on('click','.sideNav3',function(){  
    $(this).unbind('click').attr('class','selected3'); 
    $('.selected2').attr('class','sideNav2').bind('click'); 
    $('.selected1').attr('class','sideNav1').bind('click'); 
    alert("3 selected"); 
    return false; 
}); 

http://jsfiddle.net/BHL84/14/

+3

'.live()'已被棄用了很長時間,現在已從最新版本的jQuery中刪除。不推薦。 '.on()'的委託形式是替代。請參閱我的答案中有關'.live()'替換的討論。 – jfriend00