浏览器重排、重绘、合成进阶

1、重排、重绘、合成

在进入主题之前先讲讲浏览器渲染过程

  • HTML被HTML解析器解析成DOM Tree

  • 接受CSS文本,将CSS文本转换成浏览器可以理解得结构——styleSheets,转换样式表 中的属性值,使其标准化,计算出DOM树中每个节点的具体样式。

    注意:

    在给DOM树中每个节点计算具体的样式时要遵循CSS的继承规则和层叠规则

  • DOM树和CSSOM树解析完成之后被合成到一起,形成渲染树。

  • 对节点进行布局计算,这个过程叫做重排,即根据渲染树计算每个节点的几何信息。

  • 绘制页面即重绘,根据生成的渲染树去绘制整个页面

    在渲染过程中重排和重绘是最耗时的过程, 一旦触发重排,我们对DOM的修改引发了DOM几何元素的变化,渲染树需要重新计算, 而重绘只会改变 背景色、文字颜色等属性样式导致样式发生变化, 使浏览器需要根据新的属性进行绘制。更比而言,重排会产生比重绘更大的开销 ,同时这也说明了一点 重绘不一定导致重排,但重排一定会导致重绘。

1.1、重排

所谓重排就是根据渲染树中每个渲染对象的信息,计算出每个渲染对象相应的几何信息(DOM对象的位置和尺寸大小),并将其放置在对应的位置上。这里要稍微提醒下,浏览器默认的布局是流式布局,也就是说如果你更改了某一个DOM节点的信息(这里信息是指会触发重排的)就需要对DOM结构进行重新计算,重新布局界面,以此同时对这个DOM节点的改变还会影响到周边的DOM,可能是全局范围也有可能是局部范围,全局范围是指从根节点开始对整个渲染树重新进行布局,例如当我们改变浏览器窗口的尺寸,或者更改了根节点某些样式,局部范围也就是指影响了某一个分支或者某一部分。

引发重排的操作:

  • 页面第一次渲染
  • 触发CSS伪类
  • 里澜起窗口尺寸发生变化
  • 元素位置、尺寸、字体发生变化
  • 增加或者删除可见的元素
  • 设置style属性

引发重排常见的属性和方法

width height margin padding display border position

overflow clientWidth clientHeight offsetWidth offsetHeight scrollTop scrollLeft

scrollIntoView() scrollTo() getComputedStyle ()

1.2、重绘

重绘就是指当页面中元素样式发生变化时不影响他在文档流中的位置,例如改变元素的背景颜色,字体颜色,浏览器并不会再去重新计算生成渲染树,他只会将新的样式赋给元素然后绘制到页面上。

触发重绘的属性:

color border-style visibility background text-decoration background-image background-position background-repeat box-shadow

1.3、合成

相较于重排和重绘,合成操作的路径就显得非常短了,并不需要触发布局和绘制两个阶段,如果采用了 GPU,那么合成的效率会非常高。所以,关于渲染引擎生成一帧图像的几种方式,按照效率我们推荐合成方式优先,若实在不能满足需求,那么就再退后一步使用重绘或者重排的方式。下面主要讲讲合成的几个重要机制。

1.3.1、分层

分层就是将一个完整的页面分成很多图片,将图片叠加在一起就形成了我们的页面,每个图片就是一个图层,那为什么要引入分层呢?我们试想一下,当我们的页面非常复杂时,有的页面里要实现一些复杂的动画效果,比如点击菜单时弹出菜单的动画特效,滚动鼠标滚轮时页面滚动的动画效果,如果没有采用分层机制,从布局树直接生成目标图片的话,那么每次页面有很小的变化时,都会触发重排或者重绘机制,这会严重影响页面的渲染效率。所以就出现了现在的分层机制,当我们相对某个页面进行操作时,合成器只需要将页面对应的图层进行相应的变化操作就可以了,这样效率就明显得到提高。

注意点:

合成操作是在合成线程上完成的,这也就意味着在执行合成操作时,是不会影响到主线程执行的。这就是为什么经常主线程卡住了,但是 CSS 动画依然能执行的原因。

1.3.2、分块

如果说分层是从宏观上提升了渲染效率,那么分块则是从微观层面提升了渲染效率。通常情况下,页面的内容都要比屏幕大得多,这里将百度的页面作为参考。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WEIRtgp9-1604801915872)(C:\Users\1\Pictures\Screenshots\新建文件夹\QQ截图20201108095303.png)]

从这里我们明显就能看出百度的页面比我们的视口大得多,在显示这个页面时如果等待所有的图层都生成完毕,再进行合成的话,会产生一些不必要的开销,也会让合成图片的时间变得更久。因此,合成线程会将每个图层分割为大小固定的图块,然后优先绘制靠近视口的图块,这样就可以大大加速页面的显示速度。

1.4、性能优化

  • 减少DOM操作

    • 缓存访问DOM的样式信息,避免过度触发回流
    • 如果想多次访问一个DOM,可以先缓存它
  • 采用更优的API

    • 用querySelectorAll()代替getElementBy…()
    • 开启动画的GPU加速
    • 用时间委托来减少事件处理器的数量
  • 减少重排

    • 使用 class 操作样式,而不是频繁操作 style

    • 避免使用 table 布局 ,因为table某个元素出发reflow,纳闷整个table元素就会出发reflow

    • 批量dom 操作,例如 createDocumentFragment,或者使用框架,例如 React

    • Debounce window resize 事件

    • 将position属性设置为absolute或fixed, 这样的元素重排开销比较小,不用考虑它对其他元素的影响

    • 对 dom 属性的读写要分离

      div.style.top = "10px";
      div.style.bottom = "10px";
      div.style.right = "10px";
      div.style.left = "10px";
      console.log(div.offsetWidth);
      console.log(div.offseHeight);
      console.log(div.offsetRight);
      console.log(div.offsetLeft);
      
      //在这里只会进行一次重排,如果在输出时去修改样式那么每输出一次就会重排一次
      
    • will-change: transform 做优化

      这会提前告诉眼修改的元素将要做几何变换和透明度变换操作,这时候渲染引擎会将该元素单独实现一图层,等这些变换发生时,渲染引擎会通过合成线程直接去处理变换,这些变换并没有涉及到主线程,这样就大大提升了渲染的效率。

  • css优化

    • 减少使用js来修改元素样式。尽量用修改class名的方式操作样式
    • 动画尽量使用在绝望对点位或固定定位的元素上
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
重绘重排是CSS渲染过程中的两个重要概念。 重绘(Repaint)指的是当元素的样式发生变化,但不影响其布局时,浏览器会将新样式应用到元素上,重新绘制元素的外观。重绘的开销相对较小,不会引起布局的变化。 而重排(Reflow)指的是当页面布局发生变化时,例如修改了元素的尺寸、位置、内容等,浏览器会重新计算并更新元素的几何属性(如大小、位置),然后重新布局页面。重排的开销相对较大,因为它涉及到整个页面或部分页面的重新渲染。 重绘重排区别在于是否引起布局的变化。重绘只会重新绘制元素的外观,而不会影响其周围元素的布局;而重排会导致整个渲染树的重新构建和布局。 在性能优化方面,我们通常要尽量减少重排重绘的次数,因为它们会消耗大量的计算资源。一些常见的优化方法包括: 1. 使用 CSS3 动画或过渡代替 JavaScript 实现的动画效果,因为后者可能会导致频繁的重排重绘; 2. 使用类似 flexbox 和 grid 等布局技术,可以减少页面布局的复杂性,降低重排重绘的次数; 3. 避免频繁访问会引起重排重绘的属性,例如 offsetTop、offsetLeft、scrollTop、clientWidth 等; 4. 批量更新样式或布局,可以使用 CSS 类名的方式一次性修改多个元素的样式,而不是逐个修改; 5. 将需要执行多次重排的 DOM 操作尽量合并为一次,使用文档片段(DocumentFragment)进行缓存。 通过合理优化和减少重排重绘的次数,可以提升页面的性能和响应速度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值