前置知识点
DNS:Domain Name System 域名系统(基于RFC规范解释)
DNS是万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
DNS 用的网络协议⭐⭐⭐:
- DNS 在区域传输的时候用的 tcp
- 将一个区域文件传输到多个 DNS服务器的过程叫做区域传输
- 在域名解析的时候用的是 udp
(一)从浏览器输入url后都经历了什么⭐⭐⭐⭐⭐
- 浏览器的地址栏输入URL并按下回车
- 查看浏览器缓存,比较缓存是否过期
- 如果访问过该url,浏览器查找当前URL是否存在缓存(浏览器缓存是在本地保存资源副本),然后在缓存中查询是否有要请求的文件。
- 如果缓存查找成功,它会拦截请求,返回该资源的副本,并直接结束请求,而不会再去源服务器重新下载。
- 如果缓存查找失败,就会进入网络请求过程了
- DNS域名解析,拿到对应的IP和端口号
- 如果没有访问过该url,DNS就解析URL对应的
IP,并获取端口号
- 如果没有访问过该url,DNS就解析URL对应的
- 根据IP建立TCP连接(知识点:三次握手)
- HTTP发起请求。
- 握手成功,连接到了Web服务器,浏览器会根据解析到的IP地址和端口号发起HTTP请求。
- 服务器处理请求,浏览器接收HTTP响应
- 关闭TCP连接(知识点:四次挥手)
- 渲染页面,构建DOM树。(知识点:浏览器渲染的主要流程)
(二)浏览器渲染的主要流程是什么?⭐⭐⭐⭐⭐
- 根据HTML代码深度优先遍历生成DOM树(
DOM Tree)- DOM树由dom元素及属性节点组成,树的根是document对象
- 根据 CSS 代码 生成CSS规则树CSSOM (
CSS Rule Tree)
浏览器的CSS解析器解析css文件时,对CSS规则是从右到左匹配查找,如果选择器嵌套层数太多会造成CSS Tree加载变慢 - 将 DOM Tree 和 CSSOM 整合形成渲染树(
Render Tree) - 根据Render Tree 渲染页面(知识点:回流重绘)
- 遇到
<script>(即js代码)则暂停渲染,优先加载并执行JS代码,完成再继续
- 遇到
- 直至把Render Tree渲染完成
graph TD
HTML --> DOMTree
CSS --> CSSOM
DOMTree --> RenderTree
CSSOM --> RenderTree
RenderTree--> 渲染页面/回流重绘
- DOM树、CSSOM树和渲染树三者的构建并无先后条件和先后顺序,并非完全独立而是会有交叉并行构建的情况。因此会形成一边加载,一边解析,一边渲染的工作现象。
- 其中遇到CSS加载的时候,CSS不会阻塞DOM树的解析,但是会阻塞DOM树的渲染,并且CSS会阻塞下面的JS的执行
- 然后是JS加载,JS加载会影响DOM的解析,之所以会影响,是因为JS可能会删除添加节点,如果先解析后加载的话,DOM树还得重新解析,性能比较差。
- 如果不想阻塞DOM树的解析的话,可以给script添加一个
defer或者async的标签。
说一说defer 和 async⭐⭐⭐⭐⭐
(1)首先在正常情况下,script 标签是会阻塞 DOM 的解析的,所以我们要尽量不要把script 放到 head 里,要尽量放到 body 的最下方。这样不至于会有白屏的效果;
(2)然后是 defer和 async;他们两个是异步加载 js 代码的,都不会阻塞DOM解析
- defer(推迟):等dom 渲染完之后才运行该 js 代码
- 给 script 标签添加 defer 属性,就不会阻塞 dom 的解析了,等 dom 渲染完之后才运行该 js 代码
- 如果是多个 script 标签都添加了 defer 属性的话,那么它们是按照顺序执行的(第一个全部执行完毕之后才能执行第二个)
- defer 的 script 是在
DOMContentLoaded之前运行的。- window.onload和DOMContentLoaded区别?
① window.onload 资源全部加载完才能执行,包括图片
② DOMContentLoaded DOM渲染完成即可,图片可能尚未下载
- window.onload和DOMContentLoaded区别?
- async:等下载完成之后会立即运行js 代码
- 给 script 添加 async 属性之后,会异步下载 js 代码,等下载完成之后会立即运行js 代码。
- 多个 script 标签同时设置了 async 是没有先后顺序的,谁先加载完谁就先运行。
- 如果 script 标签没有操作任何 dom 信息,且不彼此依赖的话,可以使用 async
(三)重排与重绘 ⭐⭐⭐⭐⭐
1. 说一下重排与重绘
(1)重排 :表现为重新生成布局,重新排列元素
当
DOM的变化影响了元素的几何信息,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
- 页面至少会进行一次回流,页面第一次加载的时候。
- 当我们操作 DOM 时,使其结构发生改变,从而影响了整体布局,这个过程就会发生回流。
具体如下:- 当元素的 width、height、margin、padding、left、top 发生改变的时候会发生回流
- 使 DOM节点增减或移动
- 读写 offset、client、scroll 时,浏览器为了获取这些值,会进行回流操作
- 使用 window.getComputedStyle的时候
(2)重绘 :表现为某些元素的外观被改变
当改变元素时,只是改变了它的外观,比如背景颜色等,而没有影响到它的布局,这个时候会发生重绘
回流必将引起重绘;重绘不一定会引起回流
2. 如何触发重排和重绘?
任何改变用来构建渲染树的信息都会导致一次重排或重绘:
- 添加、删除、更新DOM节点
- 通过
display: none隐藏一个DOM节点:触发重排和重绘 - 通过
visibility: hidden隐藏一个DOM节点:只触发重绘,因为没有几何变化 - 移动或者给页面中的DOM节点添加动画
- 添加一个样式表,调整样式属性
- 用户行为,例如调整窗口大小,改变字号,或者滚动。
3. 如何避免或减少重排和重绘?
- 尽量避免频繁使用style,而是使用修改class的方式
- 使用 creeateDocumentFragment
- 对于 resize 和 scroll 进行防抖节流处理
集中改变样式,不要一条一条地修改 DOM 的样式。- 不要把 DOM 结点的属性值放在循环里当成循环里的变量。
- 为动画的 HTML 元件使用
fixed或absoult的position,那么修改他们的 CSS 是不会 reflow 的。 - 不使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。
- 尽量只修改
position:absolute或fixed元素,对其他元素影响不大 - 动画开始
GPU加速,translate使用3D变化 - 提升为合成层
- 将元素提升为合成层有以下优点:
- 合成层的位图,会交由 GPU 合成,比 CPU 处理要快
- 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层
- 对于 transform 和 opacity 效果,不会触发 layout 和 paint 提升合成层的最好方式是使用 CSS 的 will-change 属性: