用于DOM修改的高效Javascript

时间:2012-07-07 10:34:03

标签: javascript html dom browser reflow

说,我有一个我想用Javascript处理的HTML文件。例如:

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

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

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

或者,有没有办法在一堆中进行所有dom修改,即在所有修改完成后才会触发回流?

4 个答案:

答案 0 :(得分:6)

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

非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(当然不是理想的HTML)感到满意,那么值得考虑。

最后,如果速度至关重要并且您需要进行大量计算或字符串处理,那么您可能希望利用Web工作者。这些不能直接与DOM对话,但你可以将任务外包给他们,而且至关重要的是,他们在一个单独的线程上异步工作。

答案 1 :(得分:3)

documentElement移除document,修改它并将其重新添加回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

答案 2 :(得分:0)

我认为由浏览器来决定重排内容。并且在脚本执行完成之前他们会尝试不这样做。这里需要注意的重要一点是,例如,当您将div附加到文档正文时,它会导致DOM重新计算。为此,您可以使用documentFragment追加元素,然后将其自身分段到主体。虽然在你的情况下,如果你需要将1个元素附加到不同的容器,它将无济于事。

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

答案 3 :(得分:-1)

我认为在页面加载之前你无法处理样式或DOM元素。 首先它加载然后你开始调整页面。 我会加载页面隐藏调整它并显示。 隐藏的方法:

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