当我运行此脚本时,页面会不断加载并最终冻结。这是因为每次创建元素时,都会调用主DOMContentLoaded
侦听器吗?
如果是这样,我如何才能停止这种递归行为,而仅将一个节点添加到每个现有节点中?
//Waits for page to load
document.addEventListener('DOMContentLoaded', function() {
//Get all elements
var items = document.getElementsByTagName("*");
//Loop through entire DOM
for (var i = 0; i < items.length; i++) {
//If it is not a text node
if (!(items[i].nodeType == 3)){
//Create a div
var newDiv = document.createElement("div");
//Add div to current object
items[i].appendChild(newDiv);
}
}
});
最佳答案
这是因为items
引用了“活动列表”。这意味着,如果DOM的任何更新与原始选择器匹配,它们都将反映在列表中。
因为要附加div
,并且选择器选择所有元素,所以它会添加到列表中,将所有后续成员推入索引,因此迭代将继续。
为了避免这种情况,请在进行迭代之前为集合创建一个非活动副本。
var items = Array.from(document.getElementsByTagName("*"));
仅供参考,可以删除
if (!(items[i].nodeType == 3)){
,因为getElementsByTagName
永远不会返回文本节点。如果您支持非常老的IE版本,则可能需要检查
.nodeType === 1
,因为其中一些老版本在使用"*"
时包含注释节点。最后,您可以使用现代功能对此进行一些整理。
document.addEventListener('DOMContentLoaded', () => {
for (const el of [...document.getElementsByTagName("*")]) {
var newDiv = el.appendChild(document.createElement("div"));
// Work with newDiv
}
});
关于javascript - document.createElement是否继续触发DOMContentLoaded事件监听器?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42321093/