bibi7 / fe-daily-increase

一个记录开发日常和奇奇怪怪的点的repo
MIT License
5 stars 0 forks source link

浏览器的渲染以及其中的重绘和重排 #20

Open bibi7 opened 5 years ago

bibi7 commented 5 years ago

link to #19 顺便写写这块的东西好了

bibi7 commented 5 years ago

首先要搞清楚的概念是,浏览器是怎么渲染一个页面的。 在浏览器下载完全部的资源后,从开始解析资源,到真正绘制一个页面,主要经历了如下步骤:

  1. html被html解析器解析成dom tree
  2. css被css解析器解析成css tree
  3. 合并dom tree和css tree为render tree
  4. 节点信息计算,根据以上的render tree计算出实际每个节点的宽、高等其他信息,这个过程被叫做Layout(Webkit)或者Reflow(Mozilla)
  5. 绘制Painting(Webkit),把已经计算好的render tree整体绘制出来。
bibi7 commented 5 years ago

重排

在讲重排(也叫回流reflow)之前,我们要知道:浏览器是渲染默认是采用流式布局。这点还是很重要的。

在一些更改操作中更改了dom的信息,比如宽高或者display等方式,这个时候会触发重排。这个时候,不只是dom元素自身,包括整个接下去的流以及其他元素要怎么排列,都是属于必须计算的消耗。对整个dom结构的重新计算以及布局,重排也就是重新走了一遍上文中的步骤4

具体会产生重排的一系列操作如下(就不算页面初始化的那次layout了):

  1. 元素位置发生改变
  2. 元素自身的尺寸发生改变
  3. 内容改变
  4. 添加或删除元素
  5. 视口浏览器是尺寸发生变化
  6. 行内style属性的改变

重绘

重绘比重排简单,资源的开销也小。在当一次修改完全不会影响整个文档流的时候,比如颜色的更改,背景色的更改,就会触发重绘。重排一定会引发重绘,重绘不一定是基于重排。

一些提高性能的方法

每一次的重排都是对浏览器性能的一次消耗,那么如何避开一些不必要的重排就显得十分有必要了。 1、现代浏览器对重排做过相关优化,有自己的渲染队列机制,一些相靠近的重排会合并成一次,比如:

div.style.left = '10px';
div.style.top = '10px';

改变了两次style应该会触发两次重排,但是浏览器会合并成一次,但如果中间穿插了一条console的话:

div.style.left = '10px';
console.log('some info');
div.style.top = '10px';

那么这依旧是两次重排。所以一些style操作最好批量修改,让浏览器合并成一次重排渲染。

2、避免直接修改style,采用class的方式。所以第一点可以不用看了 3、由于重排引起重新计算文档流,而动画往往会引起重排,那么实现动画的dom最好position设置成absoultefixed,在脱离文档流的情况下不会影响其他元素布局。 4、善用document.fragment