DNS解析, 将域名解析成ip地址
TCP3次握手
TCP
三次握手
- 第一次: 确保
client能向server发送数据 - 第二次: 确保
serve能够收到client发来的数据, 确保server能向client发送数据 - 第三次: 确保
client能够收到server的数据
四次挥手
- 第一次:
client@server: 数据发送完毕 - 第二次:
server回复client: 收到,数据接收中...... - 第三次:
server@client: 数据接收完毕 - 第四次:
client回复server: 收到
通过微信聊天理解4次挥手
UDP
- UDP类似发短信,就算对方关机,也能将数据发出去
- TCP类似打电话,需要先拨通,建立连接后再传输数据
- http是基于tcp的
浏览器发送http请求获取数据
服务器根据http请求返回数据
浏览器接收数据
浏览器渲染数据(如下图)
graph LR
构建dom树 --> 渲染树
构建cssom树 --> 渲染树
渲染树 --> 布局树
布局树 --> 分层
分层 ---> 绘制渲染树
网络线程收到html文件后会产生一个渲染任务渲染主线程通过事件循环的方式处理这个渲染任务
html解析
两颗树
- 生成
document object model tree - 生成
css object model tree
阻塞解析
css不会阻塞解析
渲染主线程 在解析html的过程中遇到 css 不会暂停
js会阻塞解析
远古时期的 <script/>
渲染主线程在解析html的过程中遇到javaScript会暂停- 需要等待js下载
- 需要等待js执行完毕
- 一般将这种标签放到html文件的最下面
<script src="myscript.js"></script>
async
- 不需要等待js下载
- 需要等待js执行完毕
<script async src="myscript.js"></script>
defer
- 不需要等待js下载
- 不需要等待js执行完毕
- js的执行会在所有元素解析完成之后
<script defer src="myscript.js"></script>
样式计算
DOM树🌲 + CSSOM树🌲 => 带有样式的DOM树🌲(样式树)
布局
- 确定尺寸
- 确定位置
分层
将经常变动的元素单独放到一个图层,防止其对别的元素造成影响
绘制
- 对每一图层生成绘制指令
渲染主线程任务到此结束- 接下来会将绘制指令发送给
合成线程处理
重绘重排
重排: reflow
- reflow的本质是重新构建布局树
- reflow 一定会导致 repaint
修改元素大小,读取元素大小都会引起重排
为什么读取元素尺寸会引起重排
- 为了防止连续触发重排
- 修改元素大小时,触发的重排是异步的
- 因为修改元素大小时,触发的重排是
异步的, - 为了读到正确的宽度
- 读取元素尺寸会立马引起重排,确保读取的是最新值
修改元素大小会引起异步重排读取元素大小会引起同步重排
// `修改元素大小`会引起`异步重排`, 防止连续触发重排
dom.style.width = '900px'
dom.style.width = '800px'
dom.style.width = '700px'
dom.style.width = '600px'
// 读取元素尺寸会立马引起重排,确保读取的是最新值
const w = dom.clientWidth
console.log(w)
重绘: repaint
- 改变了字体颜色
- 改变了背景颜色
为什么transform效率高
transform的处理不在渲染主线程上transform的处理在合成线程上线程上transform不会引起重绘重排- 就算
js卡死,也不会影响到transform - 因为
js的执行在渲染主线程上,transform的执行在合成线程上线程上互不影响
<!DOCTYPE html>
<html>
<style>
.ball {
width: 100px;
height: 100px;
background: red;
border-radius: 50%;
}
.b1 {
animation: b1 1s alternate infinite;
}
.b2 {
animation: b2 1s alternate infinite;
position: fixed;
left: 0;
}
@keyframes b1 {
to {
transform: translate(100px)
}
}
@keyframes b2 {
to {
left: 100px
}
}
</style>
<body>
<button onclick="sleep()" >卡死</butto>
<p class="ball b1"></p>
<p class="ball b2"></p>
</body>
</html>
<script>
function sleep(time=3000) {
const start = getTime()
while(getTime() - start < time) {}
console.log('week up!!!')
}
function getTime() {
return new Date().getTime()
}
</script>