浏览器渲染机制
我们在地址栏输入url,中间经历一系列过程(略),向服务器发送请求,服务器返回数据
- 解析 HTML 标签,构建 DOM 树
- 解析 CSS 标签,构建 CSSOM(CSS对象模型) 树
- 把 DOM 和 CSSOM 组合成渲染树(render tree)
- 在渲染树的基础上进行布局,计算每个节点的几何结构
- 把每个节点绘制到屏幕上(painting)
重绘 repaint 和回流 reflow
repaint 重新绘制界面发生变化的部分
reflow 重新计算元素的几何尺寸、位置
对页面进行改动,如删除 DOM 元素,会触发回流和重绘
会触发 reflow 和 repaint 的操作有
- 添加、删除、更新 DOM 节点(reflow、repaint
- 修改元素的margin、padding、border(reflow、repaint
- display: none(reflow、repaint
- visibility: hidden(repaint
- 修改颜色、背景色(repaint
从节省性能的角度出发,
- 尽量一次性修改样式
- 给动画使用绝对定位和transform可以减少reflow(因为脱离普通流后,因此而变动的元素少了
- DOM离线后修改
CSS与JS的加载
JS加载
- 遇到script标签,如果有src发请求获取JS文件,执行JS完毕后再解析后续标签
- JS的加载和执行会阻塞后续标签的解析
- 页面中有多个js如何加载运行?
并行下载顺序执行。夜猫子的js会并行加载,只要js加载完成后立马执行。但是如果某个js已经下载完成,但其前一个js还没有下载执行,那么它必须等到前一个js下载执行完之后其才能执行(因为后面的js可能会用到前面的js
- 建议把引入JS文件放在body内部的尾部,以便让DOM尽快展现,同时方便JS操作DOM
CSS加载
- 遇到link标签,会发请求获取CSS文件,同时不影响后续标签的解析
- CSS的加载不阻塞解析,但会阻塞渲染
不阻塞解析指不影响DOM树的构建。阻塞渲染是因为CSS未加载完成导致CSSOM树未构建完成,从而无法构建渲染树,一直处于白屏状态(白屏是指页面内容展现前的一片空白
- 建议把引入CSS文件放置在head标签内,尽可能早的去加载CSS
async 与 defer
正常情况下JS的加载会阻止后续DOM结构的解析,并且多个JS会按顺序依次执行
<script async src="script.js"></script>
- async 加载和渲染后续文档元素的过程将和script.js的加载与执行并行进行(异步)
<script defer src="script2.js"></script>
- defer 加载后续文档元素的过程将和script.js 的加载并行进行(异步),但script.js 的执行要在所有元素解析完成之后执行,对多个defer的外置js按顺序执行
从URL输入到页面展现发生了什么
- 域名解析,得到IP
- 向该IP对应服务器发请求获取资源
- 后端返回HTML,浏览器解析HTML
- 遇到script标签发请求,js加载后需执行完毕才继续解析后续HTML
- 遇到link标签发请求获取css,同时继续解析后续HTML
- HTML标签解析完毕后,构建DOM树。CSS加载完毕后,构建CSSOM树,合并计算得到渲染树,渲染绘制