说,我有一个HTML文件,我想用Javascript处理它。例如:
- 添加一些 DOM 元素,如
span
或div
包装器。 - 稍微更改文档样式,例如基本字体大小,行高等。
- 使用连字符添加
­
实体。
方法是什么,即我想用最少的回流来做到这一点。
理想的情况是在第一个布局之前运行JS代码。这可能吗?我知道,在显示页面之前执行昂贵的脚本通常是一个坏主意,因为这会使页面在一段时间内看起来空白,这是一种非常糟糕的体验。但是,我需要它才能离线工作,这对我的项目来说不是问题。
或者,有没有办法在一堆中完成所有 dom 修改,即在所有更改完成后触发回流?
有几种方法。所有这些的主要目标是最终导致单个 - 或至少尽可能少 - 重排/重绘。
Off-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
文档片段
关于这个主题的一个更正式的、可能改进的变体是文档片段,这显然会带来性能优势。它们实际上是第二个独立的 DOM,没有显示。
字符串
所有这些中最快的可能是将文档构建为字符串。显而易见的含义是你不能在上面使用 DOM 方法,但如果你喜欢字符串处理和正则表达式(当然在 HTML 上不理想),可能值得考虑。
最后,如果速度至关重要,并且您有大量的计算或字符串处理要做,您可能希望利用 Web Workers。这些不能直接与 DOM 通信,但您可以将任务外包给它们,而且至关重要的是,它们在单独的线程上异步工作。
从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>
这将触发两次重排和零到两次额外的重绘。
js小提琴
浏览器决定重排内容。他们尽量在脚本执行完成之前不这样做。这里需要注意的是,例如,当您将div 附加到文档正文时,它会导致 DOM 重新计算。为此,您可以使用 documentFragment 附加元素,然后将自身片段化到正文中。虽然如果你的情况下,你需要将 1 个元素附加到不同的容器,那将没有多大帮助。
文档片段上的附加读取:http://ejohn.org/blog/dom-documentfragments/
我认为在页面加载之前您无法处理样式或 DOM 元素。首先加载它,然后开始调整页面。我会加载页面隐藏地调整它并显示。隐藏方法:
- 所有内容都加载到屏幕 X/Y 坐标之外,然后 u 将其设置为 0,0
- 目录页数据具有样式:显示:无或可见性:隐藏 http://www.w3schools.com/css/css_display_visibility.asp 查看此处了解详细信息。
- 它可以是 u 加载 1 像素 iframe 内的页面,u 作为父页面所有者可以控制子页面。完成调整后调整 iframe 大小,隐藏其框架。
- 使用Z索引并放置全尺寸非透明DIV黑色或白色,隐藏所有内容。准备好后将其删除
选择更适合您风格的产品。