本文共 2253 字,大约阅读时间需要 7 分钟。
在网页开发中,reflow和repaint是浏览器渲染过程中的两个关键步骤,了解它们的工作原理和性能影响对于优化页面性能至关重要。特别是在移动端开发中,这两个过程可能成为性能瓶颈,因此掌握相关知识至关重要。
reflow(回流)、也称为rearrange(重排),指浏览器为了重新渲染页面文档而重新计算元素位置和布局的过程。当页面布局或元素属性发生变化时,浏览器会触发回流以更新渲染树(render tree)。渲染树是一个包含所有可见DOM节点及其样式规则的树结构,浏览器通过它来生成最终的页面布局。
repaint(重绘),则是当页面中的元素需要更新样式风格但不影响布局时会发生。例如,更换背景色、改变颜色或添加阴影等操作都会触发重绘过程。需要注意的是,repaint通常伴随着reflow,而反之则不一定成立。
浏览器在渲染过程中,reflow会导致渲染树的部分或全部节点失效并重新构建,而repaint则仅更新受影响部分的样式。这些过程共同决定了页面的显示效果,但也可能对性能产生重大影响。
reflow触发的主要原因包括:
repaint通常由以下属性变化触发:
在移动端,浏览器的渲染能力远低于PC端。频繁的reflow和repaint操作会导致页面刷新率下降,影响用户体验。因此,开发者需要谨慎对待这些过程,避免不必要的性能开销。
浏览器为了防止频繁的reflow引发假死,采用了一些优化策略。例如,会收集多次的reflow操作到缓存队列中,等待合适的时机一次性处理。然而,这种优化可能会导致访问真实值(如offsetLeft、getComputedStyle等)的延迟。
为了评估代码对性能的影响,可以设计如下的测试用例:
document.addEventListener('DOMContentLoaded', function () { var date = new Date(); for (var i = 0; i < 70000; i++) { var tmpNode = document.createElement("div"); tmpNode.innerHTML = "test" + i; document.body.appendChild(tmpNode); } console.log("speed time", new Date() - date);}); 这个代码循环创建70000个div元素,每次添加都触发一次reflow。运行结果显示,PC端可以在500ms内完成,而移动端可能需要更长时间。
将频繁修改的元素设置为display: none,这样可以避免其从渲染树中移除和重新添加带来的性能开销。待需要显示时再次激活。
避免频繁调用会强制flush缓存队列的属性访问。例如:
var left = el.offsetLeft, top = el.offsetTop, s = el.style;for (var i = 0; i < 20; i++) { left += 5; top += 5; s.left = left + "px"; s.top = top + "px";} 通过替代会触发reflow的属性,减少对布局的影响。例如:
transform: translateY()替代top属性。opacity替代visibility属性。将频繁重绘的元素单独作为一个图层,可以限制其对整体布局的影响。例如:
#react { position: relative; transform: translateZ(0);} 这样可以将元素独立到一个图层中,减少对主图层的影响。
优化reflow和repaint主要包括以下两点:
通过合理使用CSS属性替代、优化DOM操作和新建图层,可以显著提升页面性能,特别是在移动端开发中。