1

概念与定义

DOMContentLoaded(DCL)

https://developers.google.com...

The DOMContentLoaded reports the time when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

意思是当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。

onload(OL)

https://developers.google.com...

The load event is fired when the page and its dependent resources have finished loading.

意思是当页面的 html、css、js、image 等资源都已经加载完之后才会触发 load 事件。

不过要想彻底理解上述定义,还需明确一些概念。

加载/下载

指浏览器把网页内容下载到本地的过程。

解析

  • 浏览器向服务器请求到了 HTML 文档后便开始解析,产物是 DOM(文档对象模型)。
  • 如果有 CSS 的会根据 CSS 生成 CSSOM(CSS 对象模型)。
  • 然后再由 DOM 和 CSSOM 合并产生渲染树。
  • 有了渲染树,知道了所有节点的样式,下面便根据这些节点以及样式计算它们在浏览器中确切的大小和位置,这就是布局阶段。
  • 有了以上这些信息,就把节点绘制到浏览器上。

v2-e4744784c328c5c7a1527ff0822c1a5d_r.jpg

在解析过程中,

  • 遇到 <script> 标签时,首先阻塞后续内容的解析,同时检查该 <script> 是否已经下载下来,如果已下载,便执行代码。
  • 遇到 <link> 标签时,不会阻塞后续内容的解析(比如 DOM 构建),检查 <link> 资源是否已下载,如果已下载,则构建 CSSOM。
  • 遇到 DOM 标签时,执行 DOM 构建,将该 DOM 元素添加到文档树中。
有一点要注意的是,在 <body> 中第一个 <script> 资源下载完成之前,浏览器会进行首次渲染,将该 <script> 标签前面的 DOM 树和 CSSOM 合并成一棵 Render 树,渲染到页面中。这是页面从白屏到首次渲染的时间节点,比较关键

HTML 文档的加载与页面的首次渲染

  1. 浏览器首先下载该地址所对应的 html 页面。
  2. 浏览器解析 HTML 页面的 DOM 结构。
  3. 开启下载线程对文档中的所有资源按优先级排序下载。
  4. 主线程继续解析文档,到达 <head> 节点 ,<head> 里的外部资源无非是外链 css 和外链 js。
  5. 解析到 <body>

    • 如果 <body> 里只包含 DOM 元素

      • 这种情况比较简单了,DOM 树构建完,页面首次渲染。
    • 如果 <body> 里包含 DOM 元素、外链 js

      • 当解析到外链 js 的时候,该 js 尚未下载到本地,则 js 之前的 DOM 会被渲染到页面上,同时 js 会阻止后面 DOM 的构建,即后面的 DOM 节点并不会添加到文档的 DOM 树中。所以,js 执行完之前,我们在页面上看不到该 js 后面的 DOM 元素。
    • 如果 <body> 里包含 DOM 元素、外链 css

      • 外链 css 不会影响 css 后面的 DOM 构建,但是会阻碍渲染。简单点说,外链 css 加载完之前,页面还是白屏。
    • 如果 <body> 里包含 DOM 元素、外链 js、外链

      • 外链 js 和外链 css 的顺序会影响页面渲染,这点尤为重要。当 <body> 中 js 之前的外链 css 未加载完之前,页面是不会被渲染的。
      • 当 <body> 中 js 之前的外链 css 加载完之后,js 之前的 DOM 树和 css 合并渲染树,页面渲染出该 js 之前的 DOM 结构。
  6. 文档解析完毕,页面重新渲染。当页面引用的所有 js 同步代码执行完毕,触发 DOMContentLoaded 事件。
  7. HTML 文档中的图片资源,js 代码中有异步加载的 css、js 、图片资源都加载完毕之后,load 事件触发。

异步脚本

async 和 defer 的区别

带有 asyncdefer 的脚本的下载是和 HTML 的解析是并行的,但是脚本的执行和 UI 线程一定是是互斥的,像下面这张图所示,async 在下载完毕后的执行会阻塞 HTML 的解析。

WX20200101-125942.png

注意,当 HTML 解析和脚本执行都完毕之后,DOMContentLoaded 才会被触发。


参考:


csujiabin
1 声望0 粉丝