大家好,我是前端西瓜哥。今天就带大家了解一下浏览器的重绘和回流。浏览器渲染过程我们先来简单了解一下一些浏览器是如何渲染页面的。进入页面时,会请求一个HTML,HTML会被解析成根节点为documentElement的DOM(DocumentObjectModel)树,也就是。然后请求CSS(层叠样式表)文件。CSS源码非常丰富,包括浏览器自带的口袋样式(User-Agentstylesheets),通过link或者@import导入的各种外部样式,style编写的内联样式,以及基于标签上style属性的内联样式。它们加载后会被解析,按照继承规则和级联规则合并成一棵CSSOM树,代表特定选择器嵌套下的最终样式。最后结合DOM和CSSOM生成渲染树(render)。渲染树会丢弃不可见的标签,例如只携带信息但不携带结构的
标签,或者设置了display:none的元素。这里的每个节点都是一个盒子(box),应用盒子模型,有自己的宽度、padding、margin等元素。渲染树生成后,先计算“布局”,然后分层,最后光栅化(渲染)。Repaint(重绘)重绘就是重绘。只发生重绘而不改变元素的物理信息。例如,如果你改变了一个元素的背景颜色,你需要重新渲染这个元素的盒子。重绘不会改变页面的布局,只是重新渲染局部区域,一般不会造成严重的性能问题。回流(reflow)重排就是重排。当一个元素的物理信息发生变化时,后续元素的位置也会发生变化。这时必须重新计算布局,计算出元素的物理信息。比如修改元素的高度,设置元素显示:none;和其他操作将导致重排。这是来自维基百科的页面回流可视化:如何避免重绘和回流以减少DOM操作。比如Vue和React通过虚拟DOM找不同,减少更新DOM的操作;尝试生成所有要添加的元素,然后一次性添加到文档流中,而不是一个一个添加;缓存要使用的布局信息。对于同时多次修改DOM的API操作,浏览器做了优化,会缓存这些操作,一次性更新。但是,如果在此过程中访问到布局相关信息(如scrollHeight、getBoundingClientRect),则会强制重新渲染以获取最新的布局数据;经常变化的元素将被放置在一个新层上。通过transform或绝对定位生成新的渲染层,防止影响文档流;归根结底,我们应该尽量避免一次频繁地修改大量DOM。好在我们平时使用Vue、React这样的框架,可以通过新旧虚拟DOM的对比,减少对真实DOM的操作,将GPU密集型转移到CPU密集型,这各有利弊。