脚本的无阻塞加载
moduleA.js 代码
console.log(“I’m A”);
/*
此处可以放 jquery 源码
使得该文件变大,以便异步加载时看效果
*/
moduleB.js 代码
console.log(“I’m B”);
同步加载
<body>
<script src=”moduleA.js” onload=”console.log(‘A loaded’)”></script>
<script src=”moduleB.js” onload=”console.log(‘B loaded’)”></script>
</body>
输出
I’m A
A loaded
I’m B
A loaded
defer 和 async
defer:在文档完成解析后,触发 DOMContentLoaded 事件前执行。如果缺少 src 属性(即内嵌脚本),该属性不应被使用,因为这种情况下它不起作用。对动态嵌入的脚本使用 async=false 来达到类似的效果。
async:是否在允许的情况下异步执行该脚本。该属性对于内联脚本无作用 (即没有 src 属性的脚本)。
defer 示例
<body>
<script defer src=”moduleA.js” onload=”console.log(‘A loaded’)”></script>
<script src=”moduleB.js” onload=”console.log(‘B loaded’)”></script>
</body>
输出
I’m B
B loaded
I’m A
A loaded
async 示例
异步加载
<body>
<script>
loadScript(“moduleA.js”, “async A loaded”);
loadScript(“moduleB.js”, “async B loaded”);
function loadScript(url, text) {
var srcEle = document.createElement(“script”);
srcEle.src = url;
srcEle.async = true;
srcEle.onload = function () {
console.log(text);
};
document.body.appendChild(srcEle);
}
</script>
</body>
动态创建的 script 标签,async 默认为 true;
输出
I’m B
async B loaded
I’m A
async A loaded
相同之处:
加载文件时不阻塞页面渲染
使用这两个属性的脚本中不能调用 document.write 方法
有脚本的 onload 的事件回调
不同之处
每一个 async 属性的脚本都在它下载结束之后立刻执行,同时会在 window 的 load 事件之前执行。所以就有可能出现脚本执行顺序被打乱的情况;
每一个 defer 属性的脚本都是在页面解析完毕之后,按照原本的顺序执行,同时会在 document 的 DOMContentLoaded 之前执行
AMD 和 CMD
AMD
RequireJS 的标准
特点:依赖前置、预执行
define([‘./a’, ‘./b’], function(a, b) {
// 运行至此,a.js 和 b.js 已经下载完成
// a 模块和 b 模块已经执行完
a.doing();
b.doing();
});
CMD
SeaJS 的标准
特点:依赖就近、懒执行
define(function(require, exports, module) {
var a = require(“./a”);
// 等待 a.js 下载、执行完
a.doing();
var b = require(“./b”);
// 等待 b.js 下载、执行完
b.doing();
});
reference
AMD 和 CMD 的区别有哪些?