<link>
标签后面。任何带有defer
属性的<script>
元素在DOM完成加载之前都不会被执行。
var script = document.createElement('script');
script.src = "file.js";
document.getElementsByTagName("head")[0].appendChild(script);
浏览器那去在<script>
元素接收完成时触发一个load
事件,可以通过侦听此事件来获得脚本加载完成时的状态。
var script = document.createElement('script');
script.onload = function () {
console.log("Script.loaded!");
};
script.src = "file.js";
document.getElementsByTagName("head")[0].appendChild(script);
//hello
//Script loaded!
IE支持另一种实现方式,它会触发一个readystatechange
事件。
<script>
元素提供一个readyState
属性,它的值在外链文件的下载过程的不同阶段会发生变化,该属性有5
中取值:
uninitialized
初始状态loading
开始下载loaded
下载完成interactive
数据完成下载但尚不可用complete
所有数据已准备就绪使用readystatechange
事件最靠谱的方式是同时检查这两种状态,只要其中任何一个触发,就删除事件处理器(确保事件不会处理两次)。
var script = document.createElement('script');
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
console.log("script loaded!");
}
};
script.src = "file.js";
document.getElementsByTagName("head")[0].appendChild(script);
//hello
使用单一的方法动态加载JS文件,下面的函数封装了标准及IE特有的实现方法:
See the Pen onreadystatechange by whjin (@whjin) on CodePen.
动态脚本加载凭借它在跨浏览器兼容性和易用的优势,成为最通用的无阻塞加载解决方案。
XMLHTTPRequest
脚本注入另一种无阻塞加载脚本的方法是使用XHR
对象获取脚本并注入页面中。此技术先创建一个XHR对象,然后用它下载JS文件,最后通过创建动态<script>
元素将代码注入页面。
var xhr = new XMLHttpRequest();
xhr.open("get", "file.js", true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
var script = document.createElement("script");
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
这种方法的主要局限性是JS文件必须与所请求的页面处于相同的域,所以JS文件不能从CDN下载。因此,大型Web应用通常不会采用XHR脚本注入技术。
向页面中添加大量JS的推荐做法只需两步:先添加动态加载所需的代码,然后加载初始化页面所需的剩下的代码。
举个例子:
<script src="loader.js"></script>
<script>
loadScript("file.js", function () {
Application.init();
})
</script>
或者直接把函数直接嵌入页面,从而避免多产生一次HTTP请求。
使用DOM工具包,只需在YUI的use()
方法中声明dom
,并且提供回调函数即可:
YUI.use("dom", function (Y) {
Y.DOM.addClass(document.body, "loaded");
});
更为通用的延迟加载工具:LazyLoad。LazyLoad是loadScript()
函数的增强版。
LazyLoad.js("file.js", function () {
Application.init();
});
LazyLoad支持下载多个JS文件,并能保证在所有浏览器中都以正确的顺序执行。要加载多个JS文件,只需给LazyLoad.js()
方法传入一个URL数组:
LazyLoad.js(["file1.js", "file2.js"], function () {
Application.init();
});
$LAB.script()
方法用来定义需要下载的JS文件,$LAB.wait()
用来指定文件下载并执行完毕后所调用的函数。LABjs鼓励链式调用,因此每个方法都会返回一个$LAB
对象的引用。要下载多个JS文件,只需链式调用另一个$LAB.script()
方法:
$LAB.script('file1.js')
.script('file2.js')
.wait(function () {
Application.init();
});
LABjs允许使用wait()
方法来指定哪些文件需要等待其他文件,为确保第一个文件最先执行,必须在第一个script()
方法后面调用wait()
。
减少JS对性能的影响:
</body>
标签之前将所有的<script>
标签放到页面底部。确保在脚本执行前页面已经完成渲染。<script>
标签的defer
属性<script>
元素来下载并执行代码