每次删除 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 浏览器)。但是在事件处理程序中 setInterval
或 setTimeout
的情况下,我们应该手动注意删除它以避免内存泄漏。这就是为什么在你的问题中,'for Javascript events best practice is always to remove events that you are no longer use'.
我知道,对于 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 浏览器)。但是在事件处理程序中 setInterval
或 setTimeout
的情况下,我们应该手动注意删除它以避免内存泄漏。这就是为什么在你的问题中,'for Javascript events best practice is always to remove events that you are no longer use'.