页面渲染过程与回流重绘
2020-04-26 本文已影响0人
李霖弢
页面渲染过程
- 解析HTML,生成DOM树,解析CSS,生成CSSOM树
- 结合(DOM)和(CSSOM)构建一个渲染树(
display:none
的元素不会进入渲染树,而visibility:hidden
会进入渲染树) - 根据渲染树和设备视口(viewport)大小进行回流(Layout),得到各DOM节点的位置、大小信息,并转为实际的像素值。
- Painting(重绘):将节点的绝对像素值发送给GPU,展示在页面上。
-
link
标签当媒体查询不符合条件时会变成异步加载,不会阻塞渲染
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">
-
script
标签会阻塞DOM构建直到js加载并执行完成
有async
,js将异步加载。
有defer
,js将异步加载,但等到所有元素解析完成之后,DOMContentLoaded 事件触发之前再执行。
回流和重绘
回流一定会触发重绘,而重绘不一定会回流(如只有颜色改变时就只发生重绘而不会引起回流)
通常有如下行为可以触发回流:
- 页面初次渲染
- 添加或删除可见的DOM元素
- 元素的位置发生变化
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
避免回流和重绘
- 避免频繁获取布局信息
浏览器正常情况下会将dom的修改加入一个队列,等达到阈值或经过一段时间一起回流,但当JS获取布局信息时会强制队列刷新,以获得实时的最新值。因此以下属性应避免频繁使用(或缓存到一个变量):
- offsetTop、offsetLeft、offsetWidth、offsetHeight
- scrollTop、scrollLeft、scrollWidth、scrollHeight
- clientTop、clientLeft、clientWidth、clientHeight
- getComputedStyle()
- getBoundingClientRect
- 动画效果会不停触发回流,使用绝对定位让其脱离文档流
- css3硬件加速(GPU加速)
对元素设置以下任意3d属性即可启用
transform: translateZ(0);
transform: translate3d(0,0,0);
transform: rotateZ(360deg);
- 合并多次对DOM和样式的修改
如使用cssText
或class代替一次性修改多个样式
const el = document.getElementById('test');
el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
- 进行一系列修改前先使DOM脱离文档流(但由于现代浏览器会使用队列来储存多次修改进行优化,因此可以不考虑)
- 隐藏元素,应用修改,重新显示
- 使用文档片段(document fragment)在当前DOM之外构建一个子树,再把它拷贝回文档。
- 将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素。