2012-07-07 27 views
5

说,我有一个我想用Javascript处理的HTML文件。例如:用于DOM修改的高效Javascript

  • 添加一些DOM元素,如spandiv包装。
  • 更改文件样式有点像基本字体大小,行高等。
  • 使用一个接力器来添加­实体。

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

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

或者,是否有一种方法可以完成所有dom修改,即所有修改完成后触发的回流?

回答

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'ing(当然不是理想的HTML),可能值得考虑。最后,如果速度至关重要,并且您有很多计算或字符串处理工作要做,那么您可能希望利用网络工作人员。这些不能直接与DOM对话,但可以将任务外包给他们,而且关键是,他们在一个单独的线程上异步工作。

0

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

上的DocumentFragment附加读:http://ejohn.org/blog/dom-documentfragments/

-1

我觉得你不能在样式或DOM元素加载页面之前工作。 首先加载然后你开始调整页面。 我会隐藏地调整它并显示加载页面。 方法来隐藏:

  1. 一切加载外屏X/Y坐标,然后ü把它0,0
  2. DIV其内容的页面数据有风情:display:none或visibility:hidden的http://www.w3schools.com/css/css_display_visibility.asp检查这里细节。
  3. 它可以加载页面内1像素的iframe,你作为父页面拥有者控制子页面。调整大小调整iframe后,隐藏其框架。
  4. 使用Z索引并放入不透明DIV黑色或白色,隐藏所有内容。当你准备好的时候将它删除

选择更适合你的风格。

+0

即使这是真的老了答案,我还是建议不要链接到w3schools.com因为这样:http://www.w3fools.com/ :) – 2015-06-10 09:44:49

3

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