AMD规范,全称是Asynchronous Module Definition,即异步模块加载机制。
AMD规范的作者亲自实现了符合AMD规范的requireJS。
一 AMD规范
在加载模块以及模块所依赖的其他模块时,都采用异步加载的方式,避免模块加载阻塞了网页的渲染进度。
二 入口文件(主模块)
<script data-main="scripts/main" src="js/require.js"></script>
require.js在加载的时候检查data-main属性,requirejs自身加载执行后,会异步加载data-main属性指向的main.js。
三 requirejs模块的定义
1.返回简单的值
// main.js
require(['moduleA'], function(a){
console.log(a);
});
//moduleA.js
define(function(){
return 1;
})
主模块main.js是入口模块,需要调用别的模块。
2.返回键值对
//moduleA.js
define({
color: "black",
size: "unisize"
});
//main.js返回结果 object{ color: "black",size: "unisize"}
//moduleA.js
define(function () {
//Do setup work here
return {
color: "black",
size: "unisize"
}
});
//main.js返回结果 object{ color: "black",size: "unisize"}
3.定义的模块还依赖其他的模块
//moduleA.js
define(['moduleB'], function(b) {
var num = 10;
return b.add(num);
}
);
//moduleB.js
define({
add: function(n){
return n+1;
}
});
四 requires依赖与一个非requirejs定义的库
1.暴露单个变量 --shim
//hello.js 没有用define(...)定义模块
function hello() {
alert("hello, world~");
}
//依赖hello.js库错误的搞法
requirejs.config({
baseUrl: '/public/js',
paths: {
hello: 'hello'
}
});
requirejs(['hello'], function(hello) {
hello(); // 这段代码会报错,提示:undefined
});
//依赖hello.js库正确的搞法
requirejs.config({
baseUrl: '/public/js',
paths: {
hello: 'hello'
},
shim: {
hello: { exports: 'hello' } //使用shim ,将某个全局变量暴露给requirejs
}
});
requirejs(['hello'], function(hello) {
hello();
});
使用shim,exports可以把某个非requirejs定义的模块中的全局变量暴露出去。
2. 暴露多个变量--shim init
// hello.js 非requirejs定义的模块
function hello() {
alert("hello, world~");
}
function hello2() {
alert("hello, world, again~");
}
//依赖非requirejs定义的hello模块,并暴露多个全局变量
requirejs.config({
baseUrl: '/public/js',
paths: {
hello: 'hello'
},
shim: {
hello: {
init: function() {
return {
hello: hello,
hello2: hello2
}
}
}
}
});
requirejs(['hello'], function(hello) {
hello.hello1();
hello.hello2();
});
五 有主模块
//这一段依赖jquery的代码会报错no defined,myjquery改为jquery就可以正确依赖
require.config({
baseUrl: '/public/js',
paths: {
myjquery: 'lib/jquery/jquery'
}
});
require(['myjquery'], function(jq) {
alert(jq);
});
因为jquery是一个有主模块,jquery.js中声名的模块名和“myjquery”不一致。
//jquery.js在define中定义了模块的名字
define('jquery', [], function() { ... });
所有其他模块在依赖有主模块时,只能使用同一个名字,这样系统只会加载一次。
六 简单包裹CommonJS使其在浏览器端可以运行
commonJS主要应用于服务器端编程(同步加载模块),requireJS支持一种简单包裹的方式。
//在commonjs代码外层包裹一层函数
define(function(require, exports, module) {...});
//在commonjs代码外层包裹一层函数,如果该模块还依赖其他模块,如moduleA.js
define(['moduleA'],function(require, exports, module) {...});
a.js和b.js的commonJS形式的代码如下:
// a.js
var a = 100;
module.exports.a = a;
// b.js
var result = require('./a');
console.log(result.a);
分别经过包裹改造之后,
// a.js 包裹后
define(function(require, exports, module) {
var a = 100;
module.exports.a = a;
});
// b.js 包裹后
define(function(require, exports, module) {
var result = require('./a');
console.log(result.a);
});