每次删除 DOM 元素之前删除事件

Remove event before remove DOM element everytime

我知道,对于 Javascript 活动,最佳做法是始终删除您不再使用的活动。但是附加到我要删除的 HTML DOM 元素的事件呢,我应该先删除事件然后删除 DOM 元素还是我可以删除 DOM 元素,而不用担心附加到它的事件?

示例:

const mainContainerEl = document.querySelector('.main-container');
const addBtnEl = document.querySelector('.add-btn');
const removeBtnEl = document.querySelector('.remove-btn');

const outputTextContent = (e) => {
     console.log(e.currentTarget.textContent);
}

addBtnEl.addEventListener('click',()=>{

     /* Click to create 5 span DOM elements and add event to each 
          one then append each one of them to mainContainerEl */

     for(let i = 1; i <= 5; i++){
          const newSpanEl = document.createElement('span');
          newSpanEl.textContent = i;
          newSpanEl.addEventListener('click', outputTextContent);
          mainContainerEl.append(newSpanEl);
     };
});



/* Should I do something like this? */

removeBtnEl.addEventListener('click',()=>{
     if(mainContainerEl.firstChild){
          const mainContainerElChildren = [...mainContainerEl.children];
          mainContainerElChildren.forEach((childEl)=>{

               /* Remove event first*/
               childEl.removeEventListener('click',outputTextContent);
               /* After the event is removed, remove the element */
               childEl.remove();

          }); 
     }
});

如果我不先删除事件而直接删除 DOM 元素,事件是否会在删除 DOM 元素后删除(垃圾收集器会收集事件和 DOM 元素并将它们从内存中释放)?

简而言之:在您的情况下,对于现代浏览器,事件将被垃圾收集,因为不再有对该函数的引用。

不能保证在所有情况下都是安全的。

示例:

const button = document.querySelector("#button");
button.onclick = () => {
  const reference = 'reference';
  setInterval(function () {
    console.log("still here: ", reference);
  }, 100);
  button.remove();
};
<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div>
      <button id="button">I'll delete myself</button>
    </div>

    <script src="src/index.js"></script>
  </body>
</html>

虽然节点被移除并且没有指向事件处理程序的引用,但由于 JavaScript 关闭,处理程序的范围仍然存在于内存中。

在大多数情况下,我们可以简单地删除节点并让垃圾回收处理事件处理程序(不过仅限现代浏览器,我不确定旧的 IE 浏览器)。但是在事件处理程序中 setIntervalsetTimeout 的情况下,我们应该手动注意删除它以避免内存泄漏。这就是为什么在你的问题中,'for Javascript events best practice is always to remove events that you are no longer use'.