当前位置:首页 > 前端 > 正文内容

重排(Reflow)与重绘(Repaint)的区别?以及如何减少重排和重绘?

virtualman2周前 (08-24)前端78

重排(Reflow)与重绘(Repaint):前端性能优化的基石

在网页开发中,我们经常听到“重排”(Reflow)和“重绘”(Repaint)这两个术语。它们是浏览器渲染页面的核心过程,也是影响页面性能的关键因素。理解它们的区别和触发条件,是进行前端性能优化的基础。


一、浏览器渲染流程简述

在深入重排和重绘之前,先简单回顾一下浏览器渲染页面的基本流程:

  1. 解析 HTML:生成 DOM 树。
  2. 解析 CSS:生成 CSSOM 树。
  3. 合并 DOM 和 CSSOM:生成渲染树(Render Tree)。
  4. 布局(Layout):计算渲染树中每个节点的几何位置(坐标、尺寸等)。
  5. 绘制(Painting):将渲染树的每个节点转换为屏幕上的像素。
  6. 合成(Compositing):将多个图层合并成最终图像显示在屏幕上。

其中,布局对应的就是重排绘制对应的就是重绘


二、什么是重排(Reflow)?

重排(也称“回流”),指的是浏览器为了重新计算 DOM 元素的几何属性(如位置、大小),从而需要更新渲染树和布局的过程。

  • 本质:重新计算元素的几何信息

  • 影响范围

    • 局部重排:只影响部分 DOM 结构。例如,修改一个 div 的宽度,可能只导致该 div 及其后代元素重新布局。
    • 全局重排:影响整个页面的布局。例如,修改 <html> 根元素的字体大小,可能导致所有文本元素都需要重新计算尺寸和位置,从而引发全局重排。全局重排成本极高。
  • 触发重排的操作示例

    • 添加、删除、修改 DOM 节点。
    • 改变元素的几何属性:width, height, padding, margin, border, top, left 等。
    • 改变浏览器窗口大小(resize 事件)。
    • 读取某些会触发布局计算的属性(见下文)。
    • 访问 offsetTop, offsetLeft, offsetWidth, offsetHeight, scrollTop, scrollLeft, clientWidth, clientHeight, getComputedStyle() 等。注意:这些属性的读取本身就会强制浏览器立即执行重排以获取最新值,这被称为“强制同步布局”(Forced Synchronous Layout),是性能杀手。

三、什么是重绘(Repaint)?

重绘,指的是当元素的外观(如颜色、背景、边框样式等)发生变化,但几何属性没有改变时,浏览器需要重新绘制该元素的过程。

  • 本质:重新绘制元素的视觉外观

  • 影响范围:通常只影响元素本身及其视觉层叠相关的区域。

  • 成本:重绘的成本远低于重排,因为它跳过了计算布局的昂贵步骤。

  • 触发重绘的操作示例

    • 改变元素的颜色:color
    • 改变背景色或背景图片:background-color, background-image
    • 改变边框颜色或可见性:border-color, visibilityvisibility: hidden 会重绘,但元素仍占据空间)。
    • 改变文本样式:font-weight, text-decoration 等。
    • 注意display: none 会触发重排(因为它移除了元素,改变了布局),而 visibility: hidden 只触发重绘

四、关键区别与关系

特性 重排 (Reflow) 重绘 (Repaint)
触发原因 几何属性改变(位置、尺寸) 外观属性改变(颜色、背景等)
执行步骤 更新渲染树 → 布局 (Layout) → 绘制 (Painting) → 合成 更新渲染树 → 绘制 (Painting) → 合成
性能成本 非常高 相对较低
是否包含 必然包含重绘 不包含重排
影响范围 可能影响局部或全局布局 通常影响局部视觉

核心关系重排一定会导致重绘,但重绘不一定导致重排。

想象一下:你修改了一个盒子的宽度(重排),它的位置和大小都变了,那么它当然需要被重新画出来(重绘)。但如果你只是把盒子从红色改成蓝色(重绘),它的位置和大小没变,就不需要重新计算布局(无重排)。


五、如何减少重排和重绘?

  1. 批量修改 DOM

    • 使用 DocumentFragment 创建一个临时容器,在容器内完成所有 DOM 操作,然后一次性插入到 DOM 树中。
    • 或者先将元素 display: none(触发一次重排),进行多次修改,再恢复 display(再触发一次重排),避免中间过程的多次重排。
  2. 避免“强制同步布局”

    • 不要在修改样式后立即读取 offsetTop 等布局属性。将读写操作分开,先完成所有写操作,再统一读取。
    // ❌ 错误:反复触发重排
    for (let i = 0; i < items.length; i++) {
        items[i].style.width = items[i].offsetWidth + 10 + 'px'; // 读写交替
    }
    
    // ✅ 正确:先读取,再修改
    const widths = items.map(item => item.offsetWidth);
    requestAnimationFrame(() => {
        items.forEach((item, i) => {
            item.style.width = widths[i] + 10 + 'px';
        });
    });
  3. 使用 CSS 类名代替直接修改样式

    • 将多条 CSS 规则定义在一个类中,通过 classList.add/remove/toggle 来切换,而不是逐个修改 style 属性。
  4. 使用 transformopacity 实现动画

    • 这两个属性可以触发合成层(Compositing Layer),浏览器可以在独立的图层上进行 GPU 加速处理,通常只涉及合成(Compositing),既不重排也不重绘,性能最佳。
  5. 优化 CSS 选择器

    • 避免使用过于复杂或低效的 CSS 选择器,减少样式计算时间。

六、总结

重排和重绘是浏览器渲染性能的“双刃剑”。频繁的重排是导致页面卡顿、动画不流畅的罪魁祸首。作为前端开发者,我们需要深刻理解它们的原理和触发条件,并在实践中采取有效的策略来最小化它们的发生。通过合理使用 DocumentFragment、避免强制同步布局、利用 CSS 类和 transform/opacity 等技巧,我们可以显著提升应用的响应速度和用户体验。记住:能不重排就不重排,能不重绘就不重绘,这是性能优化的金科玉律。

相关文章

【赛后总结】第十四届蓝桥杯软件赛Web组

结论: 题目较为贴近工程实际,但要落后社会大概5年左右。考察内容很全面,需要有比较扎实的web基础。T1:唯一一道一点都不会的题竟然是第一题。工程里用了太多css in js,忘了原声css里还有一个伪类选择器nth-of-typeT2-T6:基础题目,但是细节都拉满了,尤其是自适应页面的题。做的时...

【前端】防抖与节流的定义、区别及其代码实现

【前端】防抖与节流的定义、区别及其代码实现

一、防抖与节流是什么? 本质上两者都是前端的一种优化手段,也是前端开发中处理高频技术的关键。 如:浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能 为了优化体验,...

vuex和缓存(localStore)的主要区别

Vuex和缓存的主要区别在于它们的存储位置、‌数据类型、‌持久性、‌应用场景以及生命周期。‌ 存储位置:‌ Vuex数据存储在内存中,‌而缓存数据则存储在本地文件或内存中。‌具体来说,‌Vuex用于管理组...

vue3官方指定状态管理工具——Pinia

前言在 2020 年 9 月 Vue 3 发布正式版本之后,2021 年 2 月 Vuex 也发布了适配 Vue 3 的 4.0 版本,但是在 2021 年 8 月底,由 Vue 核心团队成员 Eduardo 主要贡献的全新 Vue 状态共享库发布 2.0 版本,并在同年 11 月,尤大正式指定 P...

CSS预处理器的优化与思考:从效率工具到工程化基石

一、引言:预处理器为何仍是前端工程的「刚需」?在原生CSS逐步支持变量(--var)、嵌套语法(CSS Nesting Level 3草案)的今天,有人质疑:“CSS预处理器是否即将退出历史舞台?” 但现实是,在中大型项目中,Sass、Less等工具依然是工程化的核心组件。它们解决的不仅是语法糖问题...

用Lottie做前端动画:从设计到落地的全流程实践

用Lottie做前端动画:从设计到落地的全流程实践

一、引言:为什么选择Lottie做动画?在前端开发中,实现复杂动画往往面临两大痛点: 手动编写CSS/JS动画代码繁琐:关键帧调试、性能优化耗时耗力,尤其是复杂交互动画 传统动画格式缺陷:GIF画质差、文件体积大;视频无法实现动态交互,且难以适配不同屏幕 Lottie的出现解决了这些...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。