jQuery .on() 事件不适用于动态添加的元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12207033/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery .on() event doesn't work for dynamically added element
提问by Rafael Adel
I'm making a project where a whole div with buttons is being inserted dynamically when user click a button, and inside that div there's a button, which when the user click on it, it does something else, like alerting something for example.
我正在制作一个项目,其中当用户单击按钮时动态插入带有按钮的整个 div,并且在该 div 内有一个按钮,当用户单击它时,它会执行其他操作,例如发出警报。
The problem is when i press on that button in the dynamically added div, nothing happens. The event doesn't fire at all.
问题是当我按下动态添加的 div 中的那个按钮时,没有任何反应。该事件根本不会触发。
I tried to add that div inside the HTML and try again, the event worked. So i guess it's because the div is dynamically added.
我尝试在 HTML 中添加该 div 并重试,该事件有效。所以我想这是因为 div 是动态添加的。
The added div has a class mainTaskWrapper
, and the button has a class checkButton
.
The event is attached using .on()
at the end of script.js
file below.
添加的div有一个类mainTaskWrapper
,按钮有一个类checkButton
。该事件附加.on()
在script.js
下面的文件末尾。
Here's my code :
这是我的代码:
helper_main_task.js :(that's the object that adds the div, you don't have to read it, as i think it's all about that div being dynamically added, but i'll put it in case you needed to)
helper_main_task.js :(这是添加div的对象,你不必阅读它,因为我认为这都是关于动态添加的div,但我会把它放在你需要的时候)
var MainUtil = {
tasksArr : [],
catArr : ["all"],
add : function(){
var MTLabel = $("#mainTaskInput").val(), //task label
MTCategory = $("#mainCatInput").val(), //task category
MTPriority = $("#prioritySlider").slider("value"), //task priority
MTContents = $('<div class="wholeTask">\
<div class="mainTaskWrapper clearfix">\
<div class="mainMarker"></div>\
<label class="mainTaskLabel"></label>\
<div class="holder"></div>\
<div class="subTrigger"></div>\
<div class="checkButton"></div>\
<div class="optTrigger"></div>\
<div class="addSubButton"></div>\
<div class="mainOptions">\
<ul>\
<li id="mainInfo">Details</li>\
<li id="mainEdit">Edit</li>\
<li id="mainDelete">Delete</li>\
</ul>\
</div>\
</div>\
</div>');
this.tasksArr.push(MTLabel);
//setting label
MTContents.find(".mainTaskLabel").text(MTLabel);
//setting category
if(MTCategory == ""){
MTCategory = "uncategorized";
}
MTContents.attr('data-cat', MTCategory);
if(this.catArr.indexOf(MTCategory) == -1){
this.catArr.push(MTCategory);
$("#categories ul").append("<li>" + MTCategory +"</li>");
}
$("#mainCatInput").autocomplete("option", "source",this.catArr);
//setting priority marker color
if(MTPriority == 2){
MTContents.find(".mainMarker").css("background-color", "red");
} else if(MTPriority == 1){
MTContents.find(".mainMarker").css("background-color", "black");
} else if(MTPriority == 0){
MTContents.find(".mainMarker").css("background-color", "blue");
}
MTContents.hide();
$("#tasksWrapper").prepend(MTContents);
MTContents.slideDown(100);
$("#tasksWrapper").sortable({
axis: "y",
scroll: "true",
scrollSpeed : 10,
scrollSensitivity: 10,
handle: $(".holder")
});
}
};
script.js :(the file where the .on() function resides at the bottom)
script.js :(.on() 函数位于底部的文件)
$(function(){
$("#addMain, #mainCatInput").on('click keypress', function(evt){
if(evt.type == "click" || evt.type =="keypress"){
if((evt.type =="click" && evt.target.id == "addMain") ||
(evt.which == 13 && evt.target.id=="mainCatInput")){
MainUtil.add();
}
}
});
//Here's the event i'm talking about :
$("div.mainTaskWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
});
回答by Felix Kling
It does not look like div.mainTaskWrapper
exist.
它看起来并不div.mainTaskWrapper
存在。
From the documentation(yes, it is actually bold):
从文档(是的,它实际上是粗体):
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to
.on()
.To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page.[...]
By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers.
事件处理程序只绑定到当前选中的元素;在您的代码调用 时,它们必须存在于页面上
.on()
。为确保元素存在且可以被选择,请在文档就绪处理程序中为页面上 HTML 标记中的元素执行事件绑定。[...]
通过选择在附加委托事件处理程序时保证存在的元素,您可以使用委托事件来避免频繁附加和删除事件处理程序的需要。
You might want to bind it to #tasksWrapper
instead:
您可能希望将其绑定到#tasksWrapper
:
$("#tasksWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
回答by GolezTrol
You need to specify a selector with on
(as a parameter) to make it behave like the old delegate
method. If you don't do that, the event will only be linked to the elements that currenly match div.mainTaskWrapper
(which do not exists yet). You need to either re-assign the event after you added the new elements, or add the event to an element that already exists, like #tasksWrapper
or the document itself.
您需要使用on
(作为参数)指定一个选择器,使其表现得像旧delegate
方法。如果您不这样做,则事件将仅链接到当前匹配的元素 div.mainTaskWrapper
(尚不存在)。您需要在添加新元素后重新分配事件,或者将事件添加到已经存在的元素,例如#tasksWrapper
文档本身。
See 'Direct and delegate events' on this page.
请参阅本页上的“直接和委托事件” 。
回答by anti000gravity
I know this is an old post but might be useful for anyone else who comes across...
我知道这是一篇旧帖子,但可能对遇到的其他人有用...
You could try:
你可以试试:
jQuery('body')on.('DOMNodeInserted', '#yourdynamicallyaddeddiv', function () {
//Your button click event
});
Here's a quick example - https://jsfiddle.net/8b0e2auu/
这是一个简单的例子 - https://jsfiddle.net/8b0e2auu/