【问题标题】:Inserting many DOM elements chokes插入许多 DOM 元素阻塞
【发布时间】:2011-02-15 10:06:49
【问题描述】:

我有一个循环,我通过document.getElementById(target).appendChild(docFragmentDiv) 将大约 500 个<div>s 插入 DOM,每个<div> 可能有 20 或 30 个后代。我最多可以插入大约 100 个,但是如果有 200 多个插入,页面会在更新 DOM 时暂时冻结。

我怎样才能避免这种窒息?现在我有一个间隔设置为每个间隔插入 50 个,间隔之间有 25 毫秒。有没有更好的方法来做到这一点?

【问题讨论】:

  • - “医生,当我将手臂举过头顶时很痛。” - “那就不要把你的手臂举过头顶。”
  • 您是否有最终页面的静态版本以确保浏览器呈现不是问题? Javascript 可能不是问题。

标签: javascript dom


【解决方案1】:

你应该使用innerHTML,并且你应该只使用一次。

为了获得最佳效率,您应该使用循环将 HTML 片段组装到字符串数组中,然后编写 document.getElementById(target).innerHTML = htmlPieces.join()

【讨论】:

  • 当我有简单的事情要做时,我会使用 DOM 方法来创建/添加元素。当我必须添加大量元素时,将它们创建为字符串并通过 innerHTML 添加速度要快几个数量级。
【解决方案2】:

像 SLaks 建议的那样使用 innerHTML 会起作用,但最好的做法是创建一个文档片段,将所有 div 节点附加到其中,然后将文档片段附加到主文档。

var docFrag = document.createDocumentFragment();

for (var i=0; i docFrag.appendChild(document.createElement("div"));
}

document.getElementById(target).appendChild(docFrag);

【讨论】:

    【解决方案3】:

    innerHtml() 几乎总是比 appendChild() 快。

    查看QuirksMode's benchmarking 了解实数。

    编辑:您是否有任何理由要间隔添加它们而不是一次性添加它们?我认为 SLaks 一次完成所有工作是正确的。

    【讨论】:

    • 我不认为你是正确的。我试过 innerHTML += 而不是 appendChild() 并且页面冻结得更快。
    • 不要做innerHTML +=。组装一个字符串数组,调用join,然后只设置一次innerHTML
    • @Slaks:这是正确的。一遍又一遍地添加innerHTML只会导致页面每次重新渲染,就像它会通过DOM方法迭代地添加元素一样。不管你做什么,只画一次页面。
    【解决方案4】:

    我不确定这是否会更快,但这是我尝试的第一件事:

    不要将它们全部添加到页面中,而是将它们全部添加到您尚未添加到页面的容器中,然后将该容器添加到页面中。

    如果这样可以提高性能,那么您可以对其进行修改以满足您的需要。

    【讨论】:

      【解决方案5】:

      请注意,直到最后一刻才将 appendChild 用于实际文档。换句话说,如果你正在做:

      var div1 = document.createElement("div");
      document.body.appendChild(div1);
      
      for (var i=0; i<500; i++) {
        var div = document.createElement("div");
        div1.appendChild(div);
      }
      

      然后,您每次在该循环中迭代都会重绘整个页面。

      如果您使用 DOM 方法,最好将其反转:

      var div1 = document.createElement("div");
      
      for (var i=0; i<500; i++) {
        var div = document.createElement("div");
        div1.appendChild(div);
      }
      
      document.body.appendChild(div1);
      

      现在您将 div 绘制到屏幕外缓冲区,并且只使页面重绘一次。

      【讨论】:

        猜你喜欢
        • 2012-09-09
        • 1970-01-01
        • 2014-10-07
        • 1970-01-01
        • 2018-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多