2013-11-21 27 views
1

我有一些代碼動態地將鏈接添加到DOM並將偵聽器添加到每個偵聽器。我遇到的問題是每次點擊其中一個鏈接時,所有的處理程序都會觸發。我試圖解決這個問題,結果總是或者我根本得不到任何答覆(就好像聽衆從未分配過)。困惑於jquery偵聽器如何工作

所以我只是通過做一些我不認爲有效的事情來解決問題。我將偵聽器分配給被動態添加的元素的id(而不是將其分配給已經在DOM中的父元素)。我認爲這是不可能的,因爲監聽器必須位於已經在DOM中的元素上?

更令人困惑的是,我正在玩jsfiddle中的一些非常類似的代碼,其結果與我所得到的結果大致相反。當我遇到問題時,它運行良好,當我解決了我的問題時,解決方案無法在jsfiddle中運行!

所以這裏是我的工作代碼。只需要更多的背景信息 - 我正在使用Firebase,並且每次在數據庫中發生child_added事件時(或者當用戶登錄時,該列表將填充數據庫中已有的所有條目)將添加這些li元素。

var songName = songSnapshot.name(); 
$(listSelector).append("<li id='" + songName + "'><a href='#'>" + songName + "</a></li>"); 
$("#" + songName).on("click", function(event) { 
    event.preventDefault(); 
    var clickedSong = $(this).text(); 
    loadCheck(clickedSong); 
}); 

而這裏的HTML:

<ul class="six columns" id="dropdowns"> 
    <li><a href="#" id="createsong">Create New Song</a></li> 
    <li> 
     <a href="#">Your Songs</a> 
     <div class="dropdown"> 
     <ul id="userSonglist"> 

     </ul> 
     </div> 
    </li> 
    <li> 
     <a href="#">All Songs</a> 
     <div class="dropdown"> 
     <ul id="publicSonglist"> 

     </ul> 
     </div> 
    </li> 
    </ul> 

任何想法是怎麼回事,這是爲什麼工作?我對jquery聽衆的理解是不正確的嗎?我花了幾乎整整一天的時間在jquery.com和其他網站上研究這一點,但這仍然讓我感到困惑。我其實只是在jsfiddle中試過這段代碼,並且它工作正常。所以顯然我錯過了/誤解了一些東西。

+1

看看這裏:http://jqfundamentals.com/chapter/events –

+0

請記住,你不能聽的東西尚不存在。但是,如果有任何孩子出現,你可以聽它的可能父母。 ('click','.item',function(event){...});' –

+0

@A。沃爾夫2 - 看事件委派有 –

回答

2

我會做的就是這樣的事情...

// P.s. this if/else statement are doing the exact same thing?! 
var songName = songSnapshot.name(); 
if (listSelector === "#publicSonglist") { 
    $(listSelector).append("<li id='" + songName + "' class='songItem'><a href='#'>" + songName + "</a></li>"); 
} 
else { 
    $(listSelector).append("<li id='" + songName + "' class='songItem'><a href='#'>" + songName + "</a></li>"); 
}; 

然後,你點擊外/添加事件:

$('#dropdowns').on("click", '.songItem', function(event) { 
    event.preventDefault(); 
    var clickedSong = $(this).text(); 
    loadCheck(clickedSong); 
}); 
+0

是的,意識到如果/ else語句在我發佈後立即做了同樣的事情,所以我擺脫了它(經過大量編輯後它結束了,而我錯過了它)。無論如何,我在發佈之前嘗試了你的想法,但它不起作用 - 如果我沒有記錯,這些鏈接就不會迴應。但正如我在上面對瑞克的迴應中指出的那樣,我的解決方案正在發揮作用,這就是爲什麼我很困惑。 –

1

你在特定的誤解?你的代碼非常好。

var songName = songSnapshot.name(); 
if (listSelector === "#publicSonglist") { 
    $(listSelector).append("<li id='" + songName + "'><a href='#'>" + songName + "</a></li>"); 
} 
else { 
    $(listSelector).append("<li id='" + songName + "'><a href='#'>" + songName + "</a></li>"); 
}; 

此時元素已被添加到dom中,因此您可以將事件綁定到它。即使它未被添加到DOM,你可以使用jQuery on()選擇父的使用事件代表團:

委託事件有優勢,他們可以處理來自被添加到文檔在 子孫元素事件晚點。

所以,你會做這樣的事情:

$('#dropdowns').on("click", '#'+songName, function(event) { 
    event.preventDefault(); 
    var clickedSong = $(this).text(); 
    loadCheck(clickedSong); 
}); 

甚至更​​慷慨的,因爲你並不真正需要的ID都:

$('#dropdowns').on("click", '.songItem', function(event) { 
    event.preventDefault(); 
    var clickedSong = $(this).text(); 
    loadCheck(clickedSong); 
}); 

希望幫助您瞭解:)

1

感謝這樣一個綜合性的問題,進一步爲當前的答案:


動態DOM

jQuery是構建於JavaScript之上,所以你的問題不只是一個jQuery一個

的方式,這兩種技術的工作就是要把文件&的元素在加載時爲它們分配功能。這意味着在加載後添加的任何元素必須被指定爲eventListener/function on the fly

您面臨的問題是您的元素沒有綁定到它們的函數,因爲它們不存在時JS分配它的函數/偵聽器。這意味着,獨立的元素添加過程中,你必須能夠將事件綁定到新元素時,他們說:


Event Delegation

爲您解決這個正確的術語是「委託」您的JS事件

委派基本上意味着,而不是聽特定的元素,JS實際上會聽父元素,然後將‘委託’的功能,它所有的孩子。這意味着,如果兒童動態添加,事件仍然會趕上他們

下面是一些對你的代碼:

$("#dropdowns").on("click", "li", function(event) { 
    event.preventDefault(); 
    var clickedSong = $(this).text(); 
    loadCheck(clickedSong); 
}); 

正如你所看到的,委託該事件的典型方法是把它放在父元素,但您也可以始終附加到$(document)(因爲這是該頁面的總體父項)

+0

是的,這就是我認爲我需要做的。但是,我擁有它的方式(沒有代表團)正在工作 - 這就是我困惑的原因。通過動態分配eventListener,你的意思是什麼?有活動代表團? –