JavaScript中的延迟加载
1.把script代码写在底部
<div>
<div class="box">
<div class="btn"></div>
</div>
</div>
<script>
let box = document.querySelector(".box");
console.log(box);//可以打印box节点
</script>
2.onload
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
window.onload=function (){
console.log("我是onload");//这个最后打印(可以打印出box节点),先执行a.js和b.js中的内容;
}
</script>
</head>
<body>
<div>
<div class="box">
<div class="btn">
</div>
</div>
</div>
<script src="../javascript/a.js"></script>
<script src="../javascript/b.js">
console.log("我是内部脚本")//不会打印
</script>
</body>
</html>
3.监听DOMContentLoaded事件
DOMContentLoaded
是在html文档加载完成即可执行(无需等待样式表、图像和子框架的完全加载);而onload
则需要html,js,css等资源全部加载完后才会触发load事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<script>
document.addEventListener("DOMContentLoaded", function () {
let box = document.querySelector(".box");
console.log(box, "DOMContentLoaded"); //先打印b.js中的内容,后打印box节点
});
</script>
</head>
<body>
<div>
<div class="box">
<div class="btn"></div>
</div>
</div>
<script src="../javascript/b.js">
console.log("我是内部脚本")//不会打印
</script>
</body>
</html>
4.延时器加载setTimeout
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
setTimeout(function (){
let box=document.querySelector(".box");
console.log(box)
},0)
</script>
</head>
<body>
<div>
<div class="box">
<div class="btn">
</div>
</div>
</div>
</body>
</html>
5.defer属性和async属性
defer
和async
都是异步加载(下载),加载的过程都不会阻塞html的解析。
5.1 defer属性
defer
是推迟的意思,defer
加载的特点如下:
- script异步加载(下载)(边下载script边解析html)
- script延迟执行(等html解析完才会执行下载的script代码)
- 按顺序执行(在html解析完之后,按顺序执行下载的script代码)
//a.js
let box=document.querySelector(".box")
console.log(box)//因为是defer,dom元素会被打印出来
//b.js
let a=11;
console.log(a)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<!-- defer会按顺序执行-->
<script defer src="../javascript/a.js"></script>
<script defer src="../javascript/b.js">
console.log("我是内部脚本")//不会打印
</script>
<script>
console.log("333"); //这个最先执行,然后执行a文件,最后执行b文件(a和b按顺序执行)
</script>
</head>
<body>
<div>
<div class="box">
<div class="btn"></div>
</div>
</div>
</body>
</html>
5.2 async属性
async是异步的意思。async
加载的特点如下:
- script异步加载(下载)(边下载script边解析html)
- script立即执行(script加载完后就会立即执行,执行script时会阻塞html的解析)
- 不按顺序执行(谁先加载完谁先执行)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<!-- async不会按顺序执行-->
<script async src="./javascript/b.js">
console.log("我是内部脚本")//不会打印
</script>
<script async src="./javascript/a.js"></script>
</head>
<body>
<div>
<div class="box">
<div class="btn"></div>
</div>
</div>
</body>
</html>
5.3 defer属性 vs async属性
5.3.1 相同点
都是并行加载(下载)script。也就是说,两者都能让script的下载阶段变成并行处理(加载的过程都不会阻塞html的解析)。
5.3.2 不同点
defer
:等html解析完才会全部执行下载的script代码;多个script(带有defer属性)标签会按顺序执行;与在底部写script很相似,区别是defer在下载阶段是异步的,相比之下可以节约点时间;
async
:script标签中的文件下载完毕之后就会立即执行script代码;多个script(带有async属性)标签不会按顺序执行(谁下载好就先执行)。
5.3.3 图示例
下面一张图就可以很直观展示二者的不同:
5.3.4 总结
- 通常情况下
defer
的使用频率较高,它能保证script之间的变量依赖。 - 需要注意的是:
async
script的资源请求时异步的,但script的执行仍然会阻塞后续渲染(单线程);defer是在html渲染完之后执行的所以不会阻塞后续html的解析。