资讯专栏INFORMATION COLUMN

性能:深入理解浏览器渲染原理 reflow & repaint

WelliJhon / 2429人阅读

摘要:之后,如果渲染树发生了变动,那么可能会触发回流或重绘中的一个或二者。在书写时要避免不必要的层级,书写时避免嵌套过深规则过于复杂,尤其是后代选择器,匹配选择器也会耗费更多的。

刚入行前端的时候是不是经常看到有文章说尽量不要用CSS通配符*,CSS选择器层叠最好不要超过三层,HTML少使用table,结构也要尽量简单一些...这一切说的不无道理,过多的使用确实会造成浏览器渲染的性能降低,当你认识了reflow和repaint之后,你会发现这些还真不能用太多。

一、浏览器渲染过程

不同的浏览器渲染过程实际上并不相同(由渲染引擎决定),但是依旧存在一致的部分,大致过程如下图:

解析HTML以构建DOM树:渲染引擎解析HTML文档,转换树中的HTML标签或JS生成的标签生成DOM节点

解析CSS以构建样式结构体:渲染引擎解析CSS(包括外部CSS文件、样式元素以及JS生成的样式)成样式结构体,根据CSS选择器计算出节点的样式

构建渲染树:从根节点递归调用,计算每一个元素的大小、位置以及每个节点所应该出现在屏幕上的精确坐标

绘制渲染树:渲染引擎遍历渲染树将其绘制出来

二、什么是 reflow & repaint

其实在上面浏览器渲染过程中的第三步和第四步分别就是回流(reflow)和重绘(repaint)。当第一次打开一个页面时,至少会有一次回流和重绘。之后,如果渲染树发生了变动,那么可能会触发回流或重绘中的一个或二者。

回流:如果渲染树的节点发生了结构性变化,例如宽高、位置、隐藏上有变化时,那么就会触发一次回流
重绘:如果渲染树的节点发生了非结构性变化,例如背景色、颜色、字体上有变化时,那么就会触发一次重绘

回流必将引起重绘,而重绘不一定会引起回流。回流的成本比重绘的成本要高得多,因为一个节点的回流很有可能导致子结点,父节点回流。

三、触发 reflow & repaint

页面初始化渲染

DOM元素的添加、修改、删除

移动DOM或着DOM发生了动画

resize浏览器窗口、滚动页面

修改DOM元素的字体颜色

激活CSS伪类

某个样式的添加、修改、删除

display: none会触发reflow,visibility: hidden只会触发repaint,因为没有发生位置变化

读取元素的某些属性(没想到吧...)

现代浏览器会对回流做优化,它会等到足够数量的变化发生,再做一次批处理回流。但是当获取某些属性时,浏览器为了获得正确的值也会提前触发回流,这样就使得浏览器的优化失效了,这些属性包括offsetLeft、offsetTop、offsetWidth、offsetHeight、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、调用了getComputedStyle()或者IE的currentStyle

四、减少 reflow & repaint

回流和重绘是不可避免的,我们只能说将它们对性能的影响减到最小,既然我们知道什么情况会触发它们,那就从这些方面入手:

让需要改变的元素进行“离线处理”,处理完后一起更新

使用DocumentFragment进行缓存操作,触发一次回流和重绘

使用display: none,触发两次回流和重绘(由于display: none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的回流,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发2次回流)

将需要多次回流的元素的position属性设为absolute或fixed(设为float没有完全脱离文档流,这个很微妙),这样元素就脱离了文档流,它的变化不会影响到其他元素的布局,不会导致一个完整回流

不要把DOM节点的属性值放在一个循环里作为循环的变量,这会导致大量地读写这个节点的属性

不要一条一条地修改样式,将多次改变样式属性的操作合并成一次(一般人也不会这样做)

不要用table布局,table中某个元素一旦触发回流就会导致table里所有的其它元素回流。在适合用table的场合,可以设置table-layout为auto或fixed,这样可以让table一行一行的渲染,这种做法也是为了限制回流的影响范围(一般我们可以通过ul li的布局替代之)

避免使用CSS的JavaScript表达式(这种规则已过时)

总之,在以后的开发中我们要尽量避免大量、频繁的操作DOM元素,因为DOM操作的代价实在是太昂贵了(这也是Virtual DOM应运而生的原因)。在书写HTML时要避免不必要的层级,书写CSS时避免嵌套过深、规则过于复杂,尤其是后代选择器,匹配选择器也会耗费更多的CPU。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/112647.html

相关文章

  • 前端性能之回流与重绘(reflow && repaint)

    摘要:写在金三银四之际。一个节点触发了,浏览器会检查中其他所有节点的显示方式一个节点触发了会导致它的祖先节点,后代节点以及在它之后的节点全部。对性能的影响大于。解决方式控制我们无力去改变,对性能损害的程度,我们能做的只有减少它们发生的次数。 写在金三银四之际。 因为种种原因想要谋求新的发展,不得已翻起了尘封已久的高程书;写起了各种经典CSS布局;回顾起记忆略显模糊的几个项目。感慨着太多太多...

    ytwman 评论0 收藏0
  • 览器渲染流程&Composite(渲染层合并)简单总结

    摘要:渲染层合并对页面中元素的绘制是在多个层上进行的。拥有两套不同的渲染路径硬件加速路径和旧软件路径中有不同类型的层负责子树和负责的子树,只有是作为纹理上传给的。整个图在中其实有几种不同的层类型渲染层,这是负责对应子树图形层,这是负责对应子树。 梳理浏览器渲染流程 首先简单了解一下浏览器请求、加载、渲染一个页面的大致过程: DNS 查询 TCP 连接 HTTP 请求即响应 服务器响应 客户...

    willin 评论0 收藏0
  • 览器渲染流程&Composite(渲染层合并)简单总结

    摘要:渲染层合并对页面中元素的绘制是在多个层上进行的。拥有两套不同的渲染路径硬件加速路径和旧软件路径中有不同类型的层负责子树和负责的子树,只有是作为纹理上传给的。整个图在中其实有几种不同的层类型渲染层,这是负责对应子树图形层,这是负责对应子树。 梳理浏览器渲染流程 首先简单了解一下浏览器请求、加载、渲染一个页面的大致过程: DNS 查询 TCP 连接 HTTP 请求即响应 服务器响应 客户...

    Channe 评论0 收藏0
  • 览器渲染流程&Composite(渲染层合并)简单总结

    摘要:渲染层合并对页面中元素的绘制是在多个层上进行的。拥有两套不同的渲染路径硬件加速路径和旧软件路径中有不同类型的层负责子树和负责的子树,只有是作为纹理上传给的。整个图在中其实有几种不同的层类型渲染层,这是负责对应子树图形层,这是负责对应子树。 梳理浏览器渲染流程 首先简单了解一下浏览器请求、加载、渲染一个页面的大致过程: DNS 查询 TCP 连接 HTTP 请求即响应 服务器响应 客户...

    zhkai 评论0 收藏0

发表评论

0条评论

WelliJhon

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<