1、概念css
当初始的 HTML 文档被彻底加载和解析完成以后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。html
load 仅用于检测一个彻底加载的页面,页面的html、css、js、图片等资源都已经加载完以后才会触发 load 事件。浏览器
2、浏览器的一些基本概念数据结构
浏览器将资源下载到本地的过程。框架
解析的意思是将一个元素经过必定的方式转换成另外一种形式。
好比 html 的解析。首先要明确,html 下载到浏览器的表现形式就是包含字符串的文件。浏览器将 html 文件里面的字符串读取到内存中,按照 html 规则,对字符串进行取词编译,将字符串转化成另外一种易于表达的数据结构。异步
好比下面的代码:fetch
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>只有css</title> <link rel="stylesheet" href="./index.css" /> </head> <body> <div id="div1"></div> <link rel="stylesheet" href="./c1.css" /> <link rel="stylesheet" href="./c3.css" /> <script src="http://test.com:9000/mine/load/case2/j1.js "></script> <link rel="stylesheet" href="./c4.css" /> <div id="div2"></div> </body> </html>
浏览器会对这个 html 文件进行编译,转化成相似下面的结构:ui
浏览器会对转化后的数据结构自上而下进行分析:首先开启下载线程,对全部的资源进行优先级排序下载(注意,这里仅仅是下载)。同时主线程会对文档进行解析: spa
⚠️在 body 中第一个 script 资源下载完成以前,浏览器会进行首次渲染,将该 script 标签前面的 DOM 树和 CSSOM 合并成一棵 Render 树,渲染到页面中。这是页面从白屏到首次渲染的时间节点。线程
将文档中的全部 DOM 元素构建成一个树型结构,DOM 构建是自上而下进行构建的,会受到 js 执行的干扰。
CSS 构建
将文档中的全部CSS资源合并。
将 DOM 树和 CSS 合并成一棵渲染树,render 树在合适的时机会被渲染到页面中。
3、HTML文档的加载与页面的首次渲染
一、浏览器首先下载该地址所对应的 html 页面。
二、浏览器解析 html 页面的 DOM 结构。
三、开启下载线程对文档中的全部资源按优先级排序下载。
四、主线程继续解析文档,到达 head 节点 ,head 里的外部资源是外链样式表和外链 js。
五、解析到 body
body 里的状况比较多,body 里可能只有 DOM 元素,可能既有 DOM、也有 css、js 等资源,js 资源又有可能异步加载图片、css、js 等。DOM 结构不一样,浏览器的解析机制也不一样,因此须要分开来讨论。
六、文档解析完毕,页面从新渲染。当页面引用的全部 js 同步代码执行完毕,触发 DOMContentLoaded 事件。
七、html 文档中的图片资源,js 代码中有异步加载的 css、js 、图片资源都加载完毕以后,load 事件触发。
以下代码所示:
<body> <!-- 白屏 --> <div id="div1"></div> <!-- 白屏 --> <link rel="stylesheet" href="./c1.css" /> <!-- 白屏 --> <link rel="stylesheet" href="./c3.css" /> <!-- 若是此时 j1.js 还没有下载到本地,则首次渲染,此时的 DOM 树 只有 div1 ,因此页面上只会显示 div1,样式是 c1.css 和 c3.css 的并集。--> <!-- 若是此时 j1.js 已经下载到本地,则先执行 j1.js,页面不会渲染,因此此时仍然是白屏。--> <!--下面的 js 阻塞了 DOM 树的构建,因此下面的 div2 没有在文档的 DOM 树中。 --> <script src="http://test.com:9000/mine/load/case2/j1.js "></script> <!-- j1.js 执行完毕,继续 DOM 解析,div2 被构建在文档 DOM 树中,此时页面上有了div2 元素,样式仍然是 c1.css 和 c3.css 的并集 --> <link rel="stylesheet" href="./c4.css" /> <!-- c4.css 加载完毕,从新构建render树,样式变成了 c1.css、c3.css 和 c4.css 的并集 --> <div id="div2"></div> <script> // 利用 performance 统计 load 加载时间。 window.onload=function(){console.log(performance.timing.loadEventStart - performance.timing.fetchStart);} </script> </body>
4、DomContentLoaded 事件的触发
DOMContentLoaded 事件在 html文档加载完毕,而且 html 所引用的内联 js、以及外链 js 的同步代码都执行完毕后触发。
5、load 事件的触发
当页面 DOM 结构中的 js、css、图片,以及 js 异步加载的 js、css 、图片都加载完成以后,才会触发 load 事件。