javascript - document.createElement 是否一直触发 DOMContentLoaded 事件监听器?

标签 javascript html dom

当我运行此脚本时,页面不断加载并最终卡住。这是因为每次我创建一个元素时,都会调用主要的 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/

相关文章:

javascript - useInterval 和 React hooks 的问题 - 无限循环

javascript - 使用 Shiny 的 clickAction 将 networkD3 中的节点链接到网站

javascript - 突出显示事件页面

javascript - 如何在HTML选择下拉列表中显示后半部分文字?

javascript - Chrome 扩展 javascript,更改文本区域中选定的文本

javascript - 如何仅传递 javascript 对象的内容,而不迭代每个值?

javascript - rails 5 : allow javascript posted image from controller

javascript - 未触发动态创建链接的 "click"

javascript - 覆盖 innerHTML 属性访问

java - 如何通过Jsoup获取 "select"html元素?