【问题标题】:Efficient Javascript for DOM modifications用于 DOM 修改的高效 Javascript
【发布时间】:2012-07-07 14:57:48
【问题描述】:

假设,我有一个 HTML 文件,我想使用 Javascript 进行处理。例如:

  • 添加一些 DOM 元素,例如 spandiv 包装器。
  • 稍微更改文档样式,例如基本字体大小、行高等。
  • 使用连字符添加­ 实体。

这样做最有效的方法是什么,即我想用最少的回流来做到这一点。

理想的情况是在第一个布局之前运行 JS 代码。这可能吗?我知道,在页面显示之前执行昂贵的脚本通常是个坏主意,因为这会使页面在一段时间内看起来是空白的,这是一种非常糟糕的体验。但是,我需要它才能离线工作,这对我的项目来说不是问题。

或者,有没有办法一次性完成所有的 dom 修改,即在所有修改完成后触发回流?

【问题讨论】:

    标签: javascript html dom browser reflow


    【解决方案1】:

    我相信由浏览器决定然后重排内容。他们尽量在脚本执行完成之前不这样做。这里需要注意的是,例如,当您将 div 附加到文档正文时,它会导致 DOM 重新计算。为此,您可以使用 documentFragment 附加元素,然后将自身分段到正文。虽然如果在您的情况下,您需要将 1 个元素附加到不同的容器,它不会有太大帮助。

    对 documentFragment 的补充阅读:http://ejohn.org/blog/dom-documentfragments/

    【讨论】:

      【解决方案2】:

      有几种方法。所有这些的主要目标是您最终导致一次 - 或至少尽可能少 - 回流/重绘。

      非 DOM 元素

      您可以在不附加到 DOM 的情况下使用元素,然后在设置完成后将所有内容附加在一起。

      唯一的问题是如果您的代码需要引用偏移尺寸,因为尚未在 DOM 中的元素没有任何元素。

      var container = document.createElement('section'); //not in the DOM yet
      //do some extensive work here to prepare the doc
      document.body.appendChild(container); //now we go to the DOM, causing a single re-paint
      

      文档片段

      此主题的更正式且可能改进的变体将是 document fragments,这会带来性能优势(显然)。它们实际上是第二个没有显示的独立 DOM。

      字符串

      可能所有这些中最快的方法是将您的文档构建为一个字符串。显而易见的含义是您不能在其上使用 DOM 方法,但如果您对字符串处理和 REGEX'ing(当然在 HTML 上不理想)感到满意,则值得考虑。

      最后,如果速度至关重要,并且您有大量的计算或字符串处理工作要做,那么您可能需要利用网络工作者。它们不能直接与 DOM 对话,但您可以将任务外包给它们,而且至关重要的是,它们在单独的线程上异步工作。

      【讨论】:

        【解决方案3】:

        我认为你不能在页面加载之前处理样式或 DOM 元素。 首先它被加载然后你开始调整页面。 我会隐藏加载页面并对其进行调整并显示。 隐藏方式:

        1. 一切都加载到屏幕 X/Y 坐标之外,然后你把它放到 0,0
        2. 内容页面数据具有样式的DIV:显示:无或可见性:隐藏http://www.w3schools.com/css/css_display_visibility.asp查看详细信息。
        3. 它可以是你在 1 像素 iframe 内加载页面,你作为父页面所有者可以控制子页面。完成你的调整后调整 iframe 的大小,隐藏它的框架。
        4. 使用 Z 索引并将全尺寸非透明 DIV 设置为黑色或白色,以隐藏所有内容。准备好后删除它

        选择更适合你的风格。

        【讨论】:

        • 即使这是一个非常古老的答案,我仍然建议不要链接到 w3schools.com,因为:w3fools.com :)
        【解决方案4】:

        document 中删除documentElement,对其进行修改并将其添加回document

        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
        <html>
            <head>
                <title>...</title>           
            </head>
            <body>
                <script type='text/javascript'>
        var docElem = document.documentElement,
            parentNode = docElem.parentNode,
            nextSibling = docElem.nextSibling;
        parentNode.removeChild(docElem); // reflow
        // ...
        docElem.lastChild.appendChild(docElem.ownerDocument.createElement('hr'));
        // ...
        parentNode.insertBefore(docElem, nextSibling); // reflow
                </script>
            </body>
        </html>
        

        这会触发两次回流和零到两次额外的重绘。

        jsFiddle

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-02-06
          • 2021-05-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多