文章目录
1. 同步加载
(1) 过程
- 正常情况下网页的加载是 js 文件和 HTML 文件进行同步加载,
一个文件加载完后, 另一个文件才会进行加载, 直到全部加载完毕.
(2) 缺点
- 过度加载 js 会影响页面效率, 因为加载工具方法的时候会阻塞文件,
- 一单网速不好, 那么整个网站将会一直等待 js 文件的加载, 而不进行后续渲染等工作
- 因此, 有些工具方法需要按需加载, 用的时候再加载, 不用的时候不进行加载.
2. 异步加载
- 定义: js 文件 html 文件异步加载, html 文件加载的同时, js 文件也在一起加载
- 异步加载有三种方式
(1) defer 异步加载
- 作用: 要等到 dom 文档全部解析完才会执行 js 文件中的工具方法
(2) async 异步加载
- 作用: 在 js 文件加载完后, 就立即执行 js 文件中的工具方法, 不必等待 dom 文件解析
(3) 创建 script 插入到 DOM 中, 加载完后调用方法
- 作用: 动态插入 js 文件加载, 真正做到用的时候再进行 js 文件的加载
- 示例
<script type = "text/javascript">
1. 创建一个 script 标签, 并用变量 script 接收该标签
var script = document.createElement('script');
2. 给标签的 type 属性赋值
script.type = "text/javascript";
3. 给标签的 src 属性赋值, 赋予目标 js 文件的路径
script.src = "target.js";
4. 当下面这一行执行时, 才会将该标签插入页面中, js文件才会去加载
document.head.appendChild(script);
5. 可以用生成的 script 元素调用其自身的 load 事件, 来使当 js 文件下载完后在执行文件内的方法
script.onload = function(){
theFunctionInTarget();
}
-
备注
(1) 第四步的插入标签的操作可以放在类似一些按钮绑定的 function 之中,
这样可以让按钮点击时才去加载这个 js 文件
(2) js 文件如果没有被加载, 它里面的方法是不能被系统识别的, 这是显而易见的,
因此在第五步要用到回调函数, 给 script 在加载完后的 onload 事件中绑定一个功能函数,
函数中的参数 callback 就是 js 文件 -
按钮加载示例
<body>
<button id="theBTN">testtt</button>
<script>
function loadScript() {
var thescript = document.createElement('script');
thescript.type = "text/javascript";
thescript.src = "scripts/target.js";
document.body.appendChild(thescript);
//thescript.onload = afterLoad;
thescript.addEventListener('load', afterLoad);
}
function afterLoad() {
saywords(1234);
}
var theBTN = document.getElementById('theBTN');
theBTN.addEventListener('click', loadScript);
</script>
</body>
3. js 加载时间线
-
创建 document 对象, 开始解析 web 页面,
解析 HTML 元素和它们的文本内容后添加 Element 对象和 Text 节点到文档中,
这个阶段document.readyState = 'loading'
-
遇到 link 外部 css, 创建线程加载, 并继续解析文档
-
遇到 script 外部 js, 并且没有设置 defer 或 async, 浏览器加载, 并阻塞,
等待 js 加载完成并执行该脚本, 然后继续解析文档 -
遇到 script 外部 js, 并且设置了 defer 或 async, 浏览器创建线程加载,
并同时继续解析文档. 对于 async 属性的脚本, 脚本加载完后立即执行
( 注: 异步禁止使用document.write()
方法 ) -
遇到 img 等, 先正常解析 dom 结构, 然后浏览器异步加载 src, 并接续解析.
-
当文档解析完成时,
document.readyState = 'interactive'
. -
文档解析完成后, 所有设置有 defer 的脚本会按照顺序执行.
( 注意与 async 的不同, 但同样禁止使用document.write()
方法 ) -
document 对象触发 DOMContentLoaded 事件,
这也标志着程序执行从同步脚本执行阶段, 转化为事件驱动阶段 -
当所有 async 的脚本加载完后并执行后, img 等加载完成后,
document.readyState = 'complete'
, window 对象触发 load 事件 -
从此, 以异步响应方式处理用户输入, 网络事件等