dom重绘和重排

217 阅读4分钟

概述:

虽然这些都是老生常谈的问题了,要想真正的理解这两个概念还要从浏览器的原理出发,也有很多博客论述的很清楚,但是还是总结一下比较好。

URL从输入到页面展示的过程
  1. 用户在浏览器的地址栏输入访问的URL地址。浏览器会先根据这个URL查看浏览器缓存-系统缓存-路由器缓存,若缓存中有,直接跳到第6步操作,若没有,则按照下面的步骤进行操作。

  2. 浏览器根据输入的URL地址解析出主机名。

  3. 浏览器将主机名转换成服务器ip地址。浏览器先查找本地DNS缓存列表,看缓存里面是否存在这个ip,如果有则进入第4步,如果缓存中不存在这个ip地址,就再向浏览器默认的DNS服务器发送查询请求,同时缓存当前这个ip到DNS缓存列表中。更详细步骤参考DNS查找域名的过程

  4. 拿到ip地址后,浏览器再从URL中解析出端口号。

  5. 拿到ip和端口后,浏览器会建立一条与目标Web服务器的TCP连接,也就是传说中的三次握手。传送门:完整的tcp链接

  6. 浏览器向服务器发送一条HTTP请求报文。

  7. 服务器向浏览器返回一条HTTP响应报文。

  8. 关闭连接 浏览器解析文档。

  9. HTML被HTML解析器解析成DOM Tree, css则被css解析器解析成CSSOM Tree。

  10. DOM Tree和CSSOM Tree解析完成后,被附加到一起,形成渲染树(Render Tree)。

  11. 节点信息计算(重排),这个过程被叫做Layout(Webkit)或者Reflow(Mozilla)。即根据渲染树计算每个节点的几何信息。

  12. 渲染绘制(重绘),这个过程被叫做(Painting 或者 Repaint)。即根据计算好的信息绘制整个页面。

一、重绘

从字面上理解就是dom重新绘制,绘制什么呢? 外观,与外观有关系的属性,比如color,vidibility,opacity等。但不会对布局有影响。

二、重排

1.是引起DOM树重新计算的行为

2.dom元素的几何变化

3.当前元素的重排也会带来相关元素的重排,容器节点渲染树改变时,也会触发子节点的重新计算,也会触发其后续兄弟节点的重排,祖先节点需要重新计算子节点的尺寸也会产生重排

4 .dom元素的结构变化。当树的结构变化时,节点的增减,移动也会触发重排。

5 .浏览器殷勤布局的过程,类似于树的前序遍历,是一个从上到下,从左到右的过程。通常这个过程中,当前的元素不会在影响前面已经遍历过的元素。所以,如果在body最前面插入一个元素,会导致整个文档的重新渲染,但是在最后插入一个元素,则不会影响到前面的元素.所以插入元素的时候可以这样

6 .获取某些属性:浏览器可能会对重排做了优化,会等到足够数量的变化发生,或者等到一定的时间,或者等一个线程结束,在一起处理,这样就只发生一次重排。但是你需要获取一些值的时候,浏览器为取得正确的值也会触发重排,这样使的浏览器的优化失效了。

7 .改变元素的一些样式,调整浏览器窗口大小等也将触发重排。

8 .当浏览器发现某个部分发生了变化影响到了布局,需要重新回去渲染,这个回退的过程叫做reflow

9 .元件的集合尺寸变了,我们需要重新验证并计算render tree,是render tree的一部分或全部发生了,需要重新layout

优化:

1 .将多次改变样式属性的操作合并成一次操作。那就是以后尽量都是操作class,在vue里面最好不要使用:style属性。都是操作class就可以了

2 .将多次重排的元素设为absolute或者fixed,这样元素就脱离了文档流,他的变化不会影响到其他元素,比如有动画效果的元素

3 .在内存中多次操作节点,完成之后在添加到文档中去。例如要获取异步表格,渲染到页面里面,可以先取得数据后在内存中构建整个表格的html片段,在一次性的添加到文档中去,而不是循环添加每一行

4 .由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂操作时,可以先隐藏他,操作完成之后在显示,这样只会在影藏和显示的时候触发2次重排。

5 .在需要经常取的,引起浏览器重排的属性值时,要缓存到变量

6 .图片载入的时候设置宽高

7 .把dom离线之后修改

8.分离读写操作