这是我参与「第四届青训营 」笔记创作活动的的第1天
✨ 前言
- 2022-07-23AM 第一节课:HTML
- 本文重点关注 vscode
!自动补全 html 代码块的具体含义
✨ 时间线
了解 html 代码之前首先要讨论 时间线
何为时间线?
简单来说,浏览器开始加载页面的那一刻到页面加载完全结束的这个过程中,按照顺序发生的每一件事情
为什么了解时间线?
我们都知道,从输入 url 到浏览器呈现页面的过程,其中对于 html 如何解析每一行标签,影响着整个网页的加载速度
✨ script 标签
对于 <script> 标签想必大家都不陌生,但是关于 <script> 上面属性想必大家就了解甚少了,这里只提及两个属性,defer 和 async
- 对于
script标签我们一般把他放在<body>内部,如果放在<head>内,则会阻塞代码执行,为什么会阻塞呢?
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.6/compiler-sfc.js">
因为对于外部引用的 <script>会同步下载 src 里面的脚本,并且会执行脚本里面的代码,因此阻塞浏览器阻塞的解析,怎么解决呢这个问题?
-
defer的意思:脚本会被延迟到整个页面都解析完毕后再运行,相当于告诉浏览器立即下载,但延迟执行(在浏览器解析到结束的</html>标签后才会执行) -
async:告诉浏览器立即开始下载,与 defer 不同的是,标记为 async 的脚本并不保证能按照它们出现的次序执行(告诉浏览器,不必等脚本下载和执行完后再加载页面,同样也不必等到该异步脚本下载和执行后再加载其他脚本),并且异步脚本不应该在加载期间修改 DOM。
- 就像上面图片表示的意思,当遇到
script标签defer和async都会开启异步下载,不会阻塞文档解析,但是脚本执行的时机各不相同
✨ 浏览器执行 html 代码顺序
先看一段代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.0-beta1/css/bootstrap-grid.css">
<script type="text/javascript" href="https://cdn.bootcdn.net/ajax/libs/vue/2.7.6/compiler-sfc.js"></script>
</head>
<body>
<img src="./1.jpg"/>
<div></div>
</body>
</html>
- 浏览器在解析到这个文件的同时,会生成
document对象,其实js文件开始起作用 - 读到第一行代码
<!DOCTYPE html>(不是html标签)标志着浏览器解析文档的模式,如果不加这行代码,浏览器解析模式变为怪异模式 ,可以通过document.compatMode访问浏览器兼容模式(只读属性) - 解析 html 标签,同时构建 dom 树,
document.readyState = 'loading' - 遇到
<link>外部标签,开启新的线程,异步加载css外部文件,生成 CSSOM(CSS 树) - 遇到没有设置异步加载的
script标签,阻塞文档解析,等待js脚本加载并且执行完成后,继续解析文档 - 异步加载的
<script>标签,异步加载 js 脚本并且执行,不阻塞文档解析,不能使用document.write - 解析
<body>里面的元素,解析文档遇到img标签,先解析这个节点,异步加载src里面的资源 - 文档解析,
document.readyState = 'interactive' - 带有
async的脚本开始执行 - 文档解析完成后,触发
DOMContentLoaded事件,同步的脚本文件执行阶段转向事件驱动阶段 async script加载并执行完成,img等资源加载完毕,window对象中的onload事件才触发,document.readyState = 'complete'加载完成
✨ document.onreadystatechange() 事件
上述的浏览器执行过程提到了 onreadystatechange 事件,通过一段代码来验证上述内容
console.log(document.readyState); // loading
document.onreadystatechange = function () {
console.log(document.readyState); // interactive complete
}
document.addEventListener('DOMContentLoaded', function () {
console.log('DOMContentLoaded')
}, false);
window.onload = function () {
console.log('onload');
console.log(document.readyState); // complete
}
输出顺序:
注意点:
DOMContentLoaded事件先与onload执行,大家有兴趣可以看下jquery中的入口函数源码,就是用了这个原理,减少白屏时间document.wirte()在 dom 树未构建完成前,向文档追加内容,而在window.onload中书写,清空所有内容,再追加