动态DOM事件监听器
我在遇到一个问题:通过AJAX更新DOM容器后,我的事件委托似乎会“失效”。
工作流程:
- 我有一个通过AJAX填充的容器 (
#encrage-html)。 - 我在该容器上使用事件委托,监听对动态生成的按钮 (
#remove-button) 的点击。 - 页面首次加载时,点击事件能够正常触发。
- 一旦AJAX
success函数执行并刷新#encrage-html的内部HTML,随后对新的#remove-button的点击就无法触发已绑定的函数。
我已验证:
build_html函数能够正确生成带有预期id="remove-button"的按钮。- 父元素 (
#encrage-html) 仍然在DOM中,并未被AJAX调用替换。
我的问题:
- 为什么当目标元素在委托的父节点内被替换时,事件委托会失效?
html()方法与现有事件处理程序之间是否存在冲突?- 在DOM刷新时,确保事件监听器持续有效的标准“最佳实践”模式是什么?
<!-- here is my script -->
<script>
$(function() {
const label1 = $("#label-selector");
const label2 = $("#label-selector2");
const encrageHtml = $("#encrage-html");
label1.on('change',process_to_get_items);
encrageHtml.on('click', '#remove-button', process_to_removing);
function process_to_removing(){
let lab1ID = $(label1).val();
let lab2Id = $(label2).val();
let checked = [];
$('input[name="checked-items"]:checked').each(function() {
checked.push($(this).val());
});
$.ajax({
url: "mainhome/get_items_service",
method: "POST",
data: { label1_id: lab1ID, label2_id: lab2Id, checked: checked },
dataType: "json",
success: function(response) {
let items = response.items;
encrageHtml.html(build_html(items));
},
error: function(xhr) {
}
});
}
function build_html(items){
let body = `<h2>My new section</h2>`
items.forEach(function(item) {
body += `<div>
<input type="checkbox" name="checked-items" value="${item.id}">
${item.title}
</div> `
})
if (items.length!==0){
body += `<button type="button" id="remove-button">Remove</button>`
}
return body;
}
});
</script>
<!-- here is the sql request if it helps, getting items with label 1 but not 2
"SELECT i.*
FROM items i
WHERE i.id IN (SELECT item FROM item_label WHERE label = :label_ok)
AND i.id NOT IN (SELECT item FROM item_label WHERE label= :label_exclude)
ORDER BY i.title ASC"
-->
解决方案
你的代码应该按预期工作。你已经正确使用了jQuery的事件委托机制。
除非你也重新构建/重新创建那个父级 #encrage-html,否则就没问题。
我创建了一个简单的模拟来测试你当前的实现,并做了一些极小的改进:
const label1 = $("#label-selector");
const label2 = $("#label-selector2");
const encrageHtml = $("#encrage-html");
label1.on('change', process_to_get_items);
encrageHtml.on('click', '#remove-button', process_to_removing);
// EMULATE A DUMMY MOCKUP RESPONSE
const mockResponse = () => {
const i = ~~(Math.random() * 999);
return {items: [
{ id: i+1, title: `${i+1} Item` },
{ id: i+2, title: `${i+2} Item` },
]};
};
function process_to_removing(){
let lab1ID = label1.val(); // Don't wrap again into $()
let lab2Id = label2.val(); // Don't wrap again into $()
let checked = [];
$('input[name="checked-items"]:checked').each(function() {
checked.push($(this).val());
});
/*$.ajax({
url: "mainhome/get_items_service",
method: "POST",
data: { label1_id: lab1ID, label2_id: lab2Id, checked: checked },
dataType: "json",
success: function(response) {
encrageHtml.html(build_html(response.items));
},
error: function(xhr) {
// Handle XHR error here
}
});*/
// TEST MOCKUP
setTimeout(function() {
encrageHtml.html(build_html(mockResponse().items));
}, 300);
}
function build_html(items){
let body = `<h2>My new section</h2>`
items.forEach((item) => {
body += `<div>
<label><input type="checkbox" name="checked-items" value="${item.id}">
${item.title}</label>
</div>`; // Use <label> for a better UX
});
if (items.length) {
body += `<button type="button" id="remove-button">Remove</button>`
}
return body;
}
function process_to_get_items () {
// TODO?
}
// TEST MOCKUP - INIT
encrageHtml.html(build_html(mockResponse().items));
<div id="encrage-html"></div>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
基于此,在测试完我的模拟后,将其移除;然后取消注释你的 $.ajax请求,并在控制台查看是否有任何错误。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。