一起学重绘和回流 | 掘金技术征文-双节特别篇

3,253 阅读6分钟

前言

Hello,大家好,我是Symbol卢,最近也比较忙,原本打算继续更新用大白话轻松搞定正则(上) 的文章,收到了大家的反馈帮助到了一些同学(一同学习的朋友),也是真的很开心😄 但是刚好遇见这次的征文由于某些原因就先写了这篇文章(偷偷的说:“用大白话轻松搞定正则 的下 也快写完了”),因为我的成长道路上也有很多的前辈给我很大的帮助,所以我会继续的传承下去;重绘和回流也是面试当中经常会被问到的一个问题,所以这篇文章咱就一起来学一下重绘和回流,从浏览器的渲染机制到重绘和回流,再到轻松搞定两道面试题。

浏览器的渲染机制

浏览器的渲染机制 用大白话来说就是,我们所写的HTMLCSS是通过某一个机制来将他们渲染成一个个漂亮的网页,这个机制就是浏览器的渲染机制。

浏览器渲染过程:

  • 处理 HTML 并构建 DOM
  • 处理 CSS 构建 CSS 规则树(CSSOM)
  • DOM 树 与 CSS 规则树 合并成一个渲染树(Render Tree)
  • 根据渲染树来布局,计算每个节点的位置
  • 调用 GPU 绘制,合成图层,显示在屏幕上

大家可以参考下面的图片(图片来源于网络)来理解浏览器的渲染过程:

图片来源于网络

  1. 浏览器会把HTML代码解析为一个DOM树, 在这个DOM树中的每一个节点,就是HTML的 中的每一个标签(DOM树的节点就是由HTML中的标签解析而来的);在DOM树中的节点里面包含了所有的HTML标签,这些HTMl标签其中包括display:none隐藏的标签(这个节点还在DOM树中,只不过是被隐藏掉了 ),还有用JS动态添加的元素(动态添加元素的js已经执行,这样才会把元素添加到DOM树中 )等。
  2. 解析完DOM树,才会去将CSS代码(和浏览器设置的默认样式,其中不同的浏览器的默认样式是不同的)解析为CSSOM ,在这个解析的过程浏览器会自动去除一些浏览器不认识或者错误的样式,比如低端浏览器无法识别的css3样式,IE会去掉-moz开头的样式,Firefox会去掉_开头的样式。
  3. DOM 树 与 CSS 规则树(CSSOM) 合并成一个渲染树(Render Tree),此时的Render Tree很像DOM树,但是它们的区别就是Render Tree 能识别样式,并且Render Tree的每一个节点都有自己的样式,而且Render Tree中不包含一些隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现。注意: visibility:hidden隐藏的元素还是会包含到Render Tree中的,因 visibility:hidden 会占有空间,影响布局(layout)。
  4. 有了Render Tree,浏览器有可以根据Render Tree来进行布局,计算每个节点的位置。
  5. 调用 GPU 进行绘制,合成图层,将绘制好的页面显示在屏幕上。

重绘 (Repaint)

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器只需要将新样式赋予给元素并重新绘制它,因此性能损耗比较低,这个过程称为重绘

常见的重绘操作

  1. 改变元素颜色
  2. 改变元素背景色

回流 (Reflow)

当页面中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程(这一过程中浏览器需要重新的进行计算,计算后重新的对页面布局)称为回流,又叫重排(重排可以理解为对页面重新的进行了排版)因此是较重的操作,性能损耗较高

常见的回流操作

  1. 页面初次渲染
  2. 浏览器窗口大小改变
  3. 元素尺寸/位置/内容发生改变
  4. 元素字体大小变化
  5. 添加或者删除可见的 DOM 元素
  6. 激活 CSS 伪类(:hover……)
  • 重点回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高

如何减少重排和重绘(提高性能)

由于回流和重绘会带来很大的性能开销,所以在开发中我们要尽量避免或减少回流和重绘的次数来提高性能

  1. 要避免频繁的去操作DOM,可以通过创建documentFragment,完成所有所有DOM操作后,最后再把它添加到文档中。
  2. 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
  3. 对具有复杂动画的元素使用绝对定位,使其脱离文档流,否则会引起父元素及后续元素频繁回流。
  4. 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。

面试题

display:none 与 visibility:hidden 的区别是什么?

display : none 隐藏对应的元素,在文档布局中不再分配空间(回流(重排)+重绘)

isibility:hideen 隐藏对应的元素,在文档布局中仍保留原来的空间(重绘)

使用 CSSdisplay:none 属性后,HTML 元素(对象)的宽度、高度等各种属性值都将“丢失”;而使用 visibility:hidden 属性后,HTML元素(对象)仅仅是在视觉上看不见(完全透明),而它所占据的空间位置仍然存在。

什么是重绘和重排,它们的区别是什么?

重绘:当页面元素样式的改变不影响布局时,浏览器重新对元素进行更新的过程叫做重绘。

重排:当页面元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程叫做重排也叫做回流。

区别:

  1. 重绘的性能开销较低,重排的性能开销较高;

  2. 回流(重排)一定会触发重绘,而重绘不一定会回流(重排)

历史好文

  1. 用大白话轻松搞定正则(上)

  2. js垃圾回收机制原理给你聊的明明白白

  3. ES11来了,不进来看看嘛

  4. 秒懂js作用域与作用域链

结束语

以上就是这篇文章的全部内容,希望对大家有帮助,这里不用打赏的哈,因为那些曾经帮助我的前辈们,也从来没有要求过打赏,大家可以给个👍(赞又不要钱),同样也 欢迎大家转发img

🏆 掘金技术征文|双节特别篇