目标:仅在ajax调用(添加或删除标签)后重新加载div,而不会丢失重新加载的div上的事件监听器。使用insertAdjacentHTML
似乎不是最佳选择。
前端:我有一个带有ul / li标签的侧边栏。有一个添加/创建标签的模式;每个标签旁边都有一个图标“ X”,可在点击时将其删除。
<ul>
<li><span>A</span><span class=li-untag>X</span>
<li><span>B</span><span class=li-untag>X</span>
<li><span>C</span><span class=li-untag>X</span>
<li><span>D</span><span class=li-untag>X</span>
</ul>
我的设置失败:
向php后端发送ajax(提取)调用以添加或删除标签
如果没有错误,则后端将为文章发送更新的且采用细枝格式的标签列表
innerHTML
更新了div。 innerHTML
更新将失去列表的所有事件侦听器(例如,单击X时的remove标记),直到真正刷新页面为止。在ajax调用之后,我尝试运行addeventlisteners,但是没有用。
我当前的设置基于先前的SO答案(请参见下文)使用insertAdjacentHTML
。这种(某种)可行,但是笨拙。
insertAdjacentHTML
我真的更希望让php发送整个div的更新和格式化列表。
有人建议在Vanilla js中使用更优雅的方法吗?
仅供参考:我所依靠的主要答案是:
Why can event listeners stop working after using element.innerHTML?
Is it possible to append to innerHTML without destroying descendants' event listeners?
If a DOM Element is removed, are its listeners also removed from memory?
JS eventListener click disappearing
编辑:侦听器已附加到“ li-untag”类
编辑2 :回答评论请求以获取更多代码。这是使用atomic ajax library的除去标记的标记:
for(let liUntag of document.querySelectorAll('.li-untag')){
liUntag.addEventListener("click", () => altUntag(liUntag))};
const altUntag = (el) => {
atomic("/tags", {
method: 'POST',
data: {
type: 'untag',
slug: el.getAttribute('data-slug'),
tag: el.getAttribute('data-untag')
}
}).then(function (response) {
el.closest('li').style.display = 'none';
console.log(response.data); // xhr.responseText
console.log(response.xhr); // full response
})
.catch(function (error) {
console.log(error.status); // xhr.status
console.log(error.statusText); // xhr.statusText
});
};
答案 0 :(得分:1)
此类的 best 解决方案是使用事件委托将单个侦听器附加到ul
,而不是将多个侦听器附加到每个li-untag
:>
document.querySelector('ul').addEventListener('click', ({ target }) => {
if (target.matches('.li-untag')) {
target.closest('li').remove();
}
});
如果您不想这样做,并且希望在每个li-untag
元素上保留一个侦听器,则可以插入新的HTML,然后对<li>
进行排序,并将侦听器附加到每个新的li-untag
:
const addListeners = () => {
document.querySelectorAll('.li-untag').forEach((span) => {
span.addEventListener('click', ({ target }) => {
target.closest('ul').remove();
});
});
};
// on document load:
addListeners();
// after inserting new HTML:
const lis = [...document.querySelectorAll('ul li')];
lis.sort((a, b) => a.children[0].textContent.localeCompare(b.children[0].textContent));
const ul = document.querySelector('ul');
lis.forEach((li) => {
ul.appendChild(li);
});
addListeners();