AMD-requirejs
AMD
是异步模块定义,典型实现requirejs
,只要在define
或者全局require
中引用了某个模块,则此模块就已经被下载且用script
标签包裹并添加到页面head
中,且利用关键词async
和页面并行加载,当模块加载完成后,按序执行模块内容,当所有模块都加载完成后,执行回调函数,回调函数不会阻塞页面其他部分的执行。
关键:
- 依赖前置
- 模块加载后立即执行,所有模块加载完成后执行回调函数,当然模块执行后才会执行回调函数
- 局部
require
可将模块的加载推迟到模块使用时,即使用时才向head
标签加入script
举例
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
console.log('DOM树开始构建'+Date.now());
window.onload = function () {
console.log('window onload'+Date.now());
}
</script>
</head>
<body>
<div id="a">CLICK ME</div>
<script type="text/javascript">
console.log('requirejs未执行,马上执行'+Date.now());
</script>
<script src="require.js" data-main="main.js"></script>
</body>
</html>
a.js
define(function () {
console.log('a开始'+Date.now());
function aa() {
console.log('aa');
}
console.log('a结束'+Date.now());
return {
aa:aa
}
});
b.js
define(function () {
console.log('b开始'+Date.now());
function bb() {
console.log('bb');
}
console.log('b开始'+Date.now());
return {
bb:bb,
}
});
main.js
require(['a'],function (a) {
a.aa();
console.log('main开始'+Date.now());
document.getElementById('a').onclick = function () {
var b = require(['b'],function (b) {
b.bb();
});
console.log('after b')
};
console.log('main执行完成'+Date.now());
});
页面点击CLICK ME
后:
DOM树开始构建1503574029463
test.html:16 requirejs未执行,马上执行1503574029468
test.html:9 window onload1503574029548
a.js:5 a开始1503574029600
a.js:11 a结束1503574029600
a.js:8 aa
main.js:6 main开始1503574029601
main.js:13 main执行完成1503574029601
main.js:11 after b
b.js:5 b开始1503574284947
b.js:10 b开始1503574284947
b.js:8 bb
未点击页面click之前,控制台资源列表项中没有b.js
,说明,局部require
进来的依赖未加载,而全局依赖a.js
已加载。且模块加载都是在window.onload
后开始的
CMD-seajs
CMD是通用模块定义,内部用Function.toString()
查找require
关键词,因此不管是模块有没有用到,都会加载出来,但是模块并不会提前执行。只有当用require
引用模块时才会执行模块。
seajs
只将main.js
用async
属性插入script
标签到head
中,目的是为了加载main.js
,此时其他模块都未加载出来,当main.js
加载完成后立即加载main
中require
引用的所有模块,main.js
执行完成后就将head
中的main.js script
标签删除。
关键
- 依赖就近
- 提前加载
- 延迟执行
requirejs
中的模块一般在main.js
的方法执行之前执行,但是seajs
会在使用时执行。
举例
//test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="a">CLICK ME</div>
<script src="sea.js" data-main="main.js"></script>
<script>
seajs.use('main.js')
</script>
</body>
</html>
main.js
define(function (require,exports,module) {
console.log('in main 1');
var a = require('./a');
console.log('in main 2');
document.getElementById('a').onclick = function () {
var b = require('./b');
b.b();
};
a.a();
});
a.js
define(function (require,exports,module) {
console.log('in a');
function a() {
console.log('a function');
}
module.exports = {
a:a
};
});
b.js
define(function (require,exports,module) {
console.log('in b');
function b() {
console.log('b function');
}
module.exports = {
b:b
};
});
在未点击页面click
之前,b.js已经在控制台资源列表中了。点击页面CLICK ME之后控制台输出:
main.js:5 in main 1//说明main.js先执行
a.js:5 in a
main.js:7 in main 2
a.js:7 a function
b.js:5 in b
b.js:7 b function