从输入https://juejin.cn到页面渲染之间的那些事(附带字节面试题)
内容提要
本文介绍了浏览器中的回流和重绘的概念,以及如何减少回流和重绘来优化浏览器性能。回流是指浏览器重新计算元素位置和几何结构的过程,常见触发回流的操作包括修改元素尺寸、位置、内容等。重绘是指根据元素样式和内容对页面进行重新绘制的过程,常见触发重绘的操作包括修改元素颜色、背景、文字样式等。文章提供了几种减少回流和重绘的方法,包括合理利用浏览器的优化策略、使用虚拟文档片段和克隆元素等。
延伸解读
回流与重绘的触发条件
文章指出,回流发生在元素的几何属性(如尺寸、位置、内容)改变时,浏览器需重新计算布局;重绘则发生在非几何属性(如颜色、背景)改变时,仅重新绘制。关键结论是回流必然导致重绘,但重绘不一定引发回流。理解这一区别有助于在开发中判断哪些操作更耗性能。
浏览器渲染队列的优化机制
浏览器通过渲染队列将短时间内的多次样式变更合并为一次回流,但某些操作会强制刷新队列,如读取offsetTop等布局属性、调用getComputedStyle、修改scrollLeft/scrollTop等。这些操作会打断批处理,导致立即回流。因此,在修改样式后应避免立即读取布局信息,以减少不必要的性能损耗。
减少回流的三种实践方案
针对循环添加100个li的场景,文章给出三种方案:先display:none再修改(两次回流)、使用DocumentFragment(一次回流)、克隆节点后整体替换(一次回流)。其中克隆方案通过替换而非直接修改DOM,更为优雅。这些方法的核心是减少直接操作真实DOM的次数,利用内存或离线操作合并变更。
面试题解析:强制回流的时机
字节面试题中,代码先读取el.offsetWidth,这会强制刷新渲染队列,但此时队列为空,不触发回流;随后两次设置width被放入队列,最终批量执行一次回流。因此只发生一次回流重绘。这题考察的是对渲染队列和强制回流时机的理解,提醒开发者注意读写分离,避免在修改样式后立即读取布局属性。
Q&A
什么是回流和重绘?
回流是浏览器重新计算元素位置和几何结构的过程,重绘是根据元素样式和内容对页面进行重新绘制的过程。
哪些操作会触发回流?
常见触发回流的操作包括修改元素的尺寸、位置、内容,添加或删除可见的DOM元素,以及改变浏览器窗口的大小。
如何减少回流和重绘以优化性能?
可以通过合理利用浏览器的优化策略、使用虚拟文档片段、克隆元素等方法来减少回流和重绘。
回流和重绘之间有什么关系?
回流一定会导致重绘,但重绘不一定会导致回流。回流涉及元素的几何属性变化,而重绘则是样式变化。
使用display:none有什么好处?
使用display:none可以减少回流次数,因为在隐藏元素时,浏览器不会计算其布局。
文档片段在减少回流方面有什么优势?
文档片段允许在内存中创建和操作DOM节点,插入时一次性添加到文档中,避免多次重排和重绘,从而提高性能。