我有一些代码可以动态地添加到DOM的链接,并为每个链接添加侦听器。我遇到的问题是,每次我点击其中一个链接时,所有处理程序都会触发。我尝试修复此问题,结果总是这样或者我根本没有得到任何响应(好像从未分配过监听器)。
所以我只是通过做一些我认为不起作用的事情来解决问题。我将侦听器分配给动态添加的元素的id(而不是将其分配给DOM中已有的父元素)。我认为这是不可能的,因为监听器必须在DOM中已经存在的元素上?
让我更加困惑的是,我在jsfiddle中使用了一些非常相似的代码,其结果几乎与我得到的相反。当我遇到问题时,它工作正常,当我解决了我的问题时,解决方案在jsfiddle中无效!
所以这是我的工作代码。更多背景 - 我正在使用Firebase,并且每次在DB中发生child_added事件时都会添加这些li元素(或者当用户登录时,列表将填充数据库中已有的所有条目)。 / p>
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中尝试了这个代码,它起作用了。所以很明显我错过了/误解了什么。
答案 0 :(得分: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);
});
答案 1 :(得分: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);
});
希望能帮助您理解:)
答案 2 :(得分:1)
感谢您提出这样一个全面的问题,进一步回答当前的答案:
动态DOM
JQuery建立在Javascript之上,因此您的问题不仅仅是JQuery的
这两种技术的工作方式是采用文件和文件的要素。在加载时为它们分配函数。这意味着加载后添加的任何元素都必须动态分配eventListener / function
您遇到的问题是您的元素没有绑定到它们的函数,因为当JS分配其函数/侦听器时它们不存在。这意味着,无论元素添加过程如何,您都必须能够在添加事件时将事件绑定到新元素:
您的修复的正确术语是“委派”您的JS事件
委托基本上意味着JS不会监听特定元素,而是实际监听父元素,然后将其功能“委托”给它的所有子元素。这意味着如果动态添加子项,事件仍将捕获它们
这里有一些代码:
$("#dropdowns").on("click", "li", function(event) {
event.preventDefault();
var clickedSong = $(this).text();
loadCheck(clickedSong);
});
正如您所看到的,委派事件的典型方法是将其放在父元素上,但您也可以始终附加到$(document)
(因为这是页面的整体父级)