写到后面有惊喜哦~
在了解浏览器的重排和重绘之前,我们需要知道的前置知识是:
在浏览器输入了一个 URL 到页面展示的过程是什么?
以简单的 GET 请求为:chestnut::
- 用户输入访问的 URL 地址。浏览器会先根据这个 URL 查看 浏览器缓存 - 系统缓存 - 路由器缓存 ,若缓存中有,直接跳到第 6 步操作,若没有,则按照下面的步骤进行操作。
- 浏览器根据输入的 URL 地址解析出主机名。
- 浏览器将主机名转换成服务器 IP 地址。浏览器先查找本地 DNS 缓存列表,看缓存里面是否存在这个 IP ,如果有则进入第 4 步,如果缓存中不存在这个 IP 地址,就再向浏览器默认的DNS服务器发送查询请求,同时缓存当前这个 IP 到 DNS 缓存列表中。
- 拿到 IP 地址后,浏览器再从 URL 中解析出端口号。
- 拿到 IP 和端口后,浏览器会建立一条与目标服务器的 TCP 连接,也就是三次握手。
- 浏览器向服务器发送一条 HTTP 请求报文。
- 服务器向浏览器返回一条 HTTP 响应报文。
- 关闭连接,浏览器解析文档(渲染页面)。
- 如果文档中有资源则重复 6、7、8 动作,直至资源全部加载完毕。
接下来,就是 浏览器对 HTML 的渲染 ,大致可以分为如下几步:
- HTML HTML 解析器解析成 DOM 树, css 则被 css 解析器解析成 CSSOM Tree 。
- DOM 树和 CSSOM Tree 解析完成后,被附加到一起,形成渲染树(Render Tree)。
- 节点信息计算(重排),根据渲染树计算每个节点的几何信息。
- 渲染绘制(重绘),根据计算好的信息绘制整个页面。
以上 4 步就是一次简单的浏览器渲染的过程。
好了,知道了过程就可以进入主题了~~
什么是重排和重绘
我们知道浏览器绘制一个页面需要下载以下几个部分的内容:
HTML 标记 / CSS / JS / 文件
下载完这些内容后会解析生成两个内部数据结构:
DOM 树 和 渲染树
- DOM 树 —— 表示页面结构,DOM树中的每一个需要显示的节点在渲染树种至少存在一个对应的节点(隐藏的DOM元素disply值为none 在渲染树中没有对应的节点)
- 渲染树 —— 表示DOM节点如何显示。渲染树中的节点被 盒 , 我们常说的 盒模型,也就是这个盒子。
一旦 DOM树 和 渲染树 构建完成,浏览器就开始显示(绘制)页面元素。
那么问题来了,什么时候发生重排 和重绘呢?
当 DOM 节点 的变化影响了元素的物理属性(宽高等),浏览器需要重新计算元素的物理属性值,同样其他元素的几何属性和位置也会因此受到影响。这时渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为 重排 。
完成重排后,浏览器会重新绘制受影响的部分到屏幕,该过程称为 重绘 。
但是并不是所有的 DOM 变化都会影响几何属性,比如改变一个元素的背景色并不会影响元素的宽和高,这种情况下只会发生重绘。
重排发生的情况
从上面我们可以知道:重排必然会导致产生重绘,但是重绘不一定会重排。
所以我们可以来概括下重排发生的情况:
- 添加或删除可见的 DOM 元素
- 元素位置改变
- 元素尺寸改变
- 元素内容改变(例如:一个文本被另一个不同尺寸的图片替代)
- 页面渲染初始化(无法避免)
- 浏览器窗口尺寸改变
知道了重排何时发生,我们才能知道如何避免重排的发生。比如说,这些都是显而易见的,我们有时候在调试的时候,不间断地改变浏览器窗口大小,导致页面反应迟钝,这就是一次次的重排重绘导致的。
如何避免重排
一般来说,重排只影响渲染树中的一小部分,但也可能影响很大的部分,甚至整个渲染树。
浏览器所需要重排的次数越少,应用程序的响应速度就越快。
因此当页面顶部的一个动画推移页面整个余下的部分时,会导致一次代价昂贵的大规模重排,让用户感到页面一顿一顿的。渲染树中需要重新计算的节点越多,情况就会越糟。
所以我们可以从以下几个地方着手避免重排:
- 尽量不要在布局信息改变时做查询(会导致渲染队列强制刷新)
- 同一个 DOM 的多个属性改变可以写在一起(减少 DOM 访问,降低强制渲染队列刷新的风险)
- 如果要批量添加 DOM ,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排(例如 fragment 元素的应用)
- 将需要多次重排的元素,设置 position 为 absolute 或 fixed ,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
前端30K面试准备,最完整面试真题分享! - 简书 https://www.jianshu.com/p/82e50d67662a
全部评论
(0) 回帖