回流(reflow)与重绘(repaint)

一、浏览器解析渲染页面过程

浏览器解析渲染页面过程

当浏览器获得一个 html 文件时,会 自上而下 的加载,并在加载过程中进行解析渲染。

  • 获取 HTML 文件并进行解析,生成 DOM (Document Object Model/文档对象模型)树;
  • 遇到 script 标签时,DOM 树构建将暂停,直至脚本执行完毕;
  • 解析 HTML 的同时也会解析 CSS,生成 CSSOM (CSS Object Model)树;
  • 将 DOM 树和 CSSOM 树结合,生成渲染树 (Render Tree);
  • 根据生成的渲染树,生成布局 (Layout) (这是一次回流),得到节点的几何信息(位置,大小);
  • 根据渲染树以及回流得到的几何信息,进行绘制 (Painting) (这是一次重绘),绘制完毕后进行 Display 展示。

二、回流 (reflow)

回流也叫重排,当 DOM 的变化影响了元素的几何信息(位置、尺寸大小等),浏览器需要重新计算元素的几何属性,将其安放在界面的正确位置,这个过程叫做回流。

2.1 回流触发时机

  • 页面初始渲染,这是开销最大的一次回流,并且避免不了;

  • 添加或删除可见的 DOM 元素;

  • 元素的位置发生变化;

  • 元素的尺寸发生变化(包括外边距、内边距、边框大小、高度和宽度等);

  • 元素内容发生变化(例如文字数量、字体、图片大小等);

  • 元素字体大小改变;

  • 改变浏览器窗口尺寸(例如 resize 事件发生时);

  • 激活 CSS 伪类(例如 :hover);

  • 设置 style 属性的值,因为通过设置 style 属性改变节点样式的话,每一次设置都会触发一次回流;

  • 查询某些属性或调用某些计算方法:offsetWidth、offsetHeight 等,除此之外,当我们调用 getComputedStyle 方法,或者 IE 里的 currentStyle 时,也会触发回流,原理是一样的,都为求一个 “即时性” 和 “准确性” 。

2.2 常见引起回流的属性和方法

widthheightmarginpadding
displayborder-widthborderposition
overflowfont-sizevertical-alignmin-height
clientWidthclientHeightclientTopclientLeft
offsetWidthoffsetHeightoffsetTopoffsetLeft
scrollWidthscrollHeightscrollTopscrollLeft
scrollIntoView()scrollTo()getComputedStyle()scrollIntoViewIfNeeded()
getBoundingClientRect()

2.3 回流影响的范围

由于浏览器渲染界面是基于流失布局模型的,所以触发回流时会对周围 DOM 重新排列,影响的范围有两种:

  • 全局范围:从根节点 html 开始对整个渲染树进行重新布局;
  • 局部范围:对渲染树的某部分或某一个渲染对象进行重新布局。

三、重绘 (repaint)

当一个元素的外观发生变化,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。

3.1 重绘触发时机

  • 可见性(visibility)和透明度(opacity)的改变;
  • 颜色的改变;
  • 背景的改变;
  • 阴影、轮廓的改变;
  • 文本方向(text-decoration)的改变等。

四、回流与重绘的关系

回流一定导致重绘,重绘不一定导致回流。

每个页面初始化渲染时至少触发一次回流和重绘。

回流和重绘的代价都很高昂,频繁回流重绘,会破坏用户体验,让页面显示变迟缓。

所以我们要尽可能避免频繁触发回流和重绘,尤其是回流。

这个网站可以帮助我们了解哪些css-properties会影响回流和重绘

五、如何尽量避免回流重绘

  • 浏览器对于回流和重绘的优化
    • 浏览器会维护一个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定数量或者到了一定的时间间隔,浏览器就会 flush 队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。
    • 但当你获取布局信息的操作的时候,例如 offsetTop 等,为了保证获取结果的准确性,就会打破浏览器的这种优化策略,强制浏览器提前 flush 队列。
  • css 中避免回流和重绘
    • 减少回流范围,尽量将需要回流的内容固定在局部范围。
    • 不要使用 table 布局,可能很小的一个改动会造成整个 table 的重新布局。不得已使用 table 的场景,可以设置 table-layout: auto; 或者 table-layout: fixed; 这样可以让 table 一行一行的渲染,同时可可以限制回流的影响范围。
    • 集中修改样式。这样可以尽可能利用浏览器的优化机制,一次回流重绘就完成渲染。
    • 避免设置多项内联样式。
    • 如果想设定元素的样式,可以通过改变元素的 class 类名(尽可能在 DOM 树的最里层)。
    • 将 DOM 离线。通过设置元素属性 display: none; 将其从页面上去掉,然后再进行后续操作,这些后续操作将不会出发回流、重绘,最后通过 display 属性显示。另外,visibility: hidden 的元素只对重绘有影响,不影响回流。
    • 使用 position: absolute / fixed; 脱离文档流。例如那些复杂的动画,对其设置 position: absolute / fixed; 尽可能地使元素脱离文档流,从而减少对其他元素的影响。
    • 利用 transform translate 去代替 left top 的变换。
    • 使用 css3 硬件加速,可以让 transform、opacity、filters 这些动画不会引起回流重绘。
    • 避免使用 css 的 JavaScript 表达式。
    • 将频繁回流或重绘的节点设置为图层。将节点设置为 video 或 iframe;为节点添加 will-change 属性。
  • js 中避免回流和重绘
    • 减少直接操作 DOM 元素。不要一条一条地修改 DOM 的样式,改用 className 来控制。
    • 分离读写操作。当需要 js 操作元素样式时,即将获取样式属性的操作集中执行,并缓存值,在需要设置样式属性时也集中处理,避免获取和设置的操作互相夹杂。因为获取、设置的操作都会引起回流。
    • 动态插入多个节点时,可以使用文档碎片(DocumnetFragment),创建后一次插入,避免多次的渲染性能。DocumnetFragment 是一个保存多个元素的容器对象(保存在内存),当更新其中的一个或者多个元素时,页面不会更新。
    • 不要把 DOM 节点的 offsetLeft 等属性值放在一个循环里当成循环里的变量。
      Fragment 是一个保存多个元素的容器对象(保存在内存),当更新其中的一个或者多个元素时,页面不会更新。
    • 不要把 DOM 节点的 offsetLeft 等属性值放在一个循环里当成循环里的变量。
    • 使用 resize 事件时,做防抖和节流处理。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
重绘和重排是CSS渲染过程中的两个重要概念。 重绘Repaint)指的是当元素的样式发生变化,但不影响其布局时,浏览器会将新样式应用到元素上,重新绘制元素的外观。重绘的开销相对较小,不会引起布局的变化。 而重排(Reflow)指的是当页面布局发生变化时,例如修改了元素的尺寸、位置、内容等,浏览器会重新计算并更新元素的几何属性(如大小、位置),然后重新布局页面。重排的开销相对较大,因为它涉及到整个页面或部分页面的重新渲染。 重绘和重排的区别在于是否引起布局的变化。重绘只会重新绘制元素的外观,而不会影响其周围元素的布局;而重排会导致整个渲染树的重新构建和布局。 在性能优化方面,我们通常要尽量减少重排和重绘的次数,因为它们会消耗大量的计算资源。一些常见的优化方法包括: 1. 使用 CSS3 动画或过渡代替 JavaScript 实现的动画效果,因为后者可能会导致频繁的重排和重绘; 2. 使用类似 flexbox 和 grid 等布局技术,可以减少页面布局的复杂性,降低重排和重绘的次数; 3. 避免频繁访问会引起重排和重绘的属性,例如 offsetTop、offsetLeft、scrollTop、clientWidth 等; 4. 批量更新样式或布局,可以使用 CSS 类名的方式一次性修改多个元素的样式,而不是逐个修改; 5. 将需要执行多次重排的 DOM 操作尽量合并为一次,使用文档片段(DocumentFragment)进行缓存。 通过合理优化和减少重排和重绘的次数,可以提升页面的性能和响应速度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值