JavaScript 的一个很重要的作用就是对 DOM 进行操作,但是对 DOM 的操作是非常占用资源的,因为这会导致浏览器执行 DOM Reflow 和 Repaint 操作。而执行了过多的页面重构操作,就会使网页变得越来越慢。
一个 HTML 网页被加载进浏览器中后,被解析为 DOM ,然后再应用样式来呈现,因此该页面的最终呈现通过两个步骤来完成:
当 DOM 元素的属性(如 color )发生变化时,浏览器会通知渲染引擎重新描绘相应的元素,此过程称为 Repaint 。
如果变化涉及元素布局,浏览器则抛弃原有属性,重新计算并把结果传递给渲染引擎以重新描绘页面元素,此过程称为 Reflow 。
这两个步骤是最耗费资源的,每次对元素的操作都会发生 Repaint 或 Reflow ,因此编写 DOM 交互时如果不注意就会导致页面性能低下。
除了在首次加载页面时必然要经历以上这两个步骤之外,还有以下行为会触发这个行为:
此时只有 Repaint ,因为不需要调整布局。
可通过以下方法优化 DOM Reflow :
例如,在游戏的一个场景中,如果要为一个 Player 加血,并假定是 5 格血,就会是 5 个能量值来呈现,因此可能会使用下面的方法:
for (var i = 0; i < 5; i++) {
var powerCell = new PowerCell();
document.body.appendChild(powerCell);
}
问题出现了,我们的目的是希望能同时出现 5 格血,这里,如果循环将 5 个 PowerCell 对象添加到 body ,会导致一个结果:浏览器对 DOM 树重构了 5 次( DOM 树重构术语被称为 Reflow )。
这里就可以使用文档片段,先把 5 格血封装为一个 DocumentFragment ,然后,再一次性添加到 body 中,这样就只会 Reflow 一次,从而大大提高性能。例如下面的代码:
var df = document.createDocumentFragment();
for (var i = 0; i < 5; i++) {
var powerCell = new PowerCell();
df.appendChild(powerCell);
}
document.body.appendChild(df);
Repaint 其实就是 CSS 导致的,因此,要注意以下事项: