当我运行此脚本时,页面不断加载并最终卡住。这是因为每次我创建一个元素时,都会调用主要的 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 的任何更新都将反射(reflect)在您的列表中,前提是它们与原始选择器匹配。
因为您要追加一个 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/