前言
本篇文章讲一个面试的知识点,在浏览器上输入URL地址直到你看到页面的那一刻发生了什么?这个问题考察了特别多的知识点,可以说贯穿了前端的一生。接下来我们一起来看一下吧。
输入URL到页面渲染 (前半段)
简单描述一下当在浏览器上输入URL会向服务器发请求拿到数据,以百度首页为例,向百度的服务器发请求,中间其实有一些操作比如找IP,握手,发送有误重新发送等等,这里不做详细的描述,我们就可以在Network中看到拿到了百度首页的Html和Css。
后半段
浏览器获取到页面资源然后后做了什么呢?
- 浏览器加载
HTML代码,将其解析成DOM树。 - 加载
CSS代码, 将其解析成CSSOM树。 DOM Tree + CSSOM Tree = render Tree。
用代码表示一下:
var DOMTree = {
div: {
id: 'app',
style: 'width: 200px, height: 200px',
children: {
div: {
clas: 'box',
children: {
p: {
text: 'hello'
}
}
}
}
}
}
var CSSOMTree = {
'#app': {
width: '200px',
height: '200px'
},
'.box': {
width: '100%',
height: 100%;
background: #000;
}
'#app .box p': {
}
}
- 计算布局,
render树中的每一个节点都会计算一遍(这就叫做回流)。 GPU绘制 一个又一个的图层 (重绘)
回流
具体定义
当页面布局和几何属性发生改变时,浏览器需要重新计算元素的位置和大小,然后重新构建页面的布局树。这个过程是比较耗费性能的,因为它需要遍历整个布局树,计算每个元素的位置和大小,并且可能会触发其他元素的回流。
触发回流的操作
- 视窗大小变化。
DOM几何属性发生变化。- 添加或者删除DOM。
offsetWidth,offsetHeight...,clientWidth,clientHeight...,scrollTop...。
局部回流
局部回流是指在DOM树中的某个特定区域内发生的回流。只有一部分DOM元素的布局发生变化,这时只需要进行局部回流。
重绘
具体定义
当元素的外观发生改变,但并不影响其布局属性(位置和大小)时,浏览器会重新绘制这个元素的外观。重绘不会引起布局树的重新构建,因此比回流的代价要小。
触发重绘的操作
- 修改元素的
color。 - 修改元素的
background。 - 修改元素的
border-radius。 - 修改元素的
box-shadow。 - 修改元素的背景图。
回流和重绘的发生是自动的,由浏览器引擎来处理的。回流一定重绘,重绘不一定回流。
优化性能
频繁的回流和重绘操作会导致页面性能下降,优化页面性能的关键之一就是尽量减少回流和重绘的发生次数。
- 当一个
DOM节点display:none时,它便不参加render树的构建。 - 页面添加额结构,使用虚拟文档片段(DocumentFragment)进行多个
DOM操作,然后一次性插入文档中。 - 避免频繁访问布局相关的属性,比如
offsetTop和offsetLeft,因为它们会触发回流。 - 使用克隆元素。
小结
减少回流和重绘对于各种类型的网页应用都非常重要,尤其是那些需要频繁操作DOM元素的复杂应用,如交互式网页、动画效果、数据可视化等。通过优化回流和重绘,可以改善网页的性能、用户体验和能源效率,提升网页应用的质量和可用性。