ajax重新加载ul / li div并保留事件侦听器(insertAdjacentHTML除外)

时间:2019-04-27 19:17:07

标签: javascript html ajax livereload insertadjacenthtml

目标:仅在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>

我的设置失败

  1. 向php后端发送ajax(提取)调用以添加或删除标签

  2. 如果没有错误,则后端将为文章发送更新的且采用细枝格式的标签列表

  3. 使用innerHTML更新了div。

innerHTML更新将失去列表的所有事件侦听器(例如,单击X时的remove标记),直到真正刷新页面为止。在ajax调用之后,我尝试运行addeventlisteners,但是没有用。

我当前的设置基于先前的SO答案(请参见下文)使用insertAdjacentHTML。这种(某种)可行,但是笨拙。

  • 删除标签不是插入问题,我所能想到的就是在单击时隐藏标签,直到刷新页面为止。
  • insertAdjacentHTML
  • 添加 标签是将新标签添加到列表中,但是不再按字母顺序排列,我必须使用一些易懂的javascript来格式化输出以匹配现有标签列表。

我真的更希望让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
    });
};

1 个答案:

答案 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();