前端模块规范:
CommonJs用在服务器端,AMD和CMD用在浏览器环境。
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
AMD:提前执行(异步加载:依赖先执行)+延迟执行
CMD:延迟执行(运行到需加载,根据顺序执行)
模块
函数写法
1
2
3
4
5
6
|
function
f1(){
//...
}
function
f2(){
//...
}
|
对象写法
1
2
3
4
5
6
7
8
9
10
11
|
var
module = {
star : 0,
f1 :
function
(){
//...
},
f2 :
function
(){
//...
}
};
module.f1();
module.star = 1;
|
模块写成一个对象,模块成员都封装在对象里,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var
module = (
function
(){
var
star = 0;
var
f1 =
function
(){
console.log(
'ok'
);
};
var
f2 =
function
(){
//...
};
return
{
f1:f1,
f2:f2
};
})();
module.f1();
//ok
console.log(module.star)
//undefined
|
外部无法访问内部私有变量
CommonJs
CommonJS是服务器端模块的规范,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
math.js
exports.add =
function
() {
var
sum = 0, i = 0, args = arguments, l = args.length;
while
(i < l) {
sum += args[i++];
}
return
sum;
};
increment.js
var
add = require(
'math'
).add;
exports.increment =
function
(val) {
return
add(val, 1);
};
index.js
var
increment = require(
'increment'
).increment;
var
a = increment(1);
//2
|
CommonJS规范:
- 一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性。
-
输出模块变量的最好方法是使用module.exports对象。
-
加载模块使用require方法,该方法读取一个文件并执行,返回文件内部的module.exports对象
开发一个服务器端组件,对模块代码作静态分析,将模块与它的依赖列表一起返回给浏览器端。 这很好使,但需要服务器安装额外的组件,并因此要调整一系列底层架构。
另一种解决思路是,用一套标准模板来封装模块定义:
1
2
3
4
5
|
define(
function
(require, exports, module) {
// The module code goes here
});
|
这套模板代码为模块加载器提供了机会,使其能在模块代码执行之前,对模块代码进行静态分析,并动态生成依赖列表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
math.js
define(
function
(require, exports, module) {
exports.add =
function
() {
var
sum = 0, i = 0, args = arguments, l = args.length;
while
(i < l) {
sum += args[i++];
}
return
sum;
};
});
increment.js
define(
function
(require, exports, module) {
var
add = require(
'math'
).add;
exports.increment =
function
(val) {
return
add(val, 1);
};
});
index.js
define(
function
(require, exports, module) {
var
inc = require(
'increment'
).increment;
inc(1);
// 2
});
|
AMD
AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。
RequireJS主要解决两个问题
- 多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器
- js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应时间越长
RequireJs也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。math.add()与math模块加载不是同步的,浏览器不会发生假死。
1
2
3
4
5
|
require([module], callback);
require([increment'],
function
(increment) {
increment.add(1);
});
|
define()函数
RequireJS定义了一个函数 define,它是全局变量,用来定义模块:
define(id?, dependencies?, factory);
参数说明:
-
id:指定义中模块的名字,。
-
依赖dependencies:是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。
-
工厂方法factory,模块初始化要执行的函数或对象。
来举个例子看看:
1
2
3
4
5
6
7
|
define(
"alpha"
, [
"require"
,
"exports"
,
"beta"
],
function
(require, exports, beta) {
exports.verb =
function
() {
return
beta.verb();
//Or:
return
require(
"beta"
).verb();
}
});
|
RequireJs使用例子
require.config是用来定义别名的,在paths属性下配置别名。然后通过requirejs(参数一,参数二);参数一是数组,传入我们需要引用的模块名,第二个参数是个回调函数,回调函数传入一个变量,代替刚才所引入的模块。
1
2
3
4
5
6
7
8
9
10
11
|
main.js
//别名配置
requirejs.config({
paths: {
jquery:
'jquery.min'
//可以省略.js
}
});
//引入模块,用变量$表示jquery模块
requirejs([
'jquery'
],
function
($) {
$(
'body'
).css(
'background-color'
,
'red'
);
});
|
引入模块也可以只写require()。requirejs通过define()定义模块,定义的参数上同。在此模块内的方法和变量外部是无法访问的,只有通过return返回才行.
1
2
3
4
5
6
7
8
|
math.js
define(
'math'
,[
'jquery'
],
function
($) {
//引入jQuery模块
return
{
add:
function
(x,y){
return
x + y;
}
};
});
|
将该模块命名为math.js保存。
1
2
3
|
require([
'jquery'
,
'math'
],
function
($,math) {
console.log(math.add(10,100));
//110
});
|
main.js引入模块方法
CMD
CMD 即Common Module Definition通用模块定义,CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,。
在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:
1
2
3
4
5
|
define(
function
(require, exports, module) {
// 模块代码
});
|
require是可以把其他模块导入进来的一个参数;而exports是可以把模块内的一些属性和方法导出的;module 是一个对象,
AMD是依赖关系前置,在定义模块的时候就要声明其依赖的模块;
CMD是按需加载依赖就近,只有在用到某个模块的时候再去require:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// CMD
define(
function
(require, exports, module) {
var
a = require(
'./a'
)
a.doSomething()
// 此处略去 100 行
var
b = require(
'./b'
)
// 依赖可以就近书写
b.doSomething()
// ...
})
// AMD 默认推荐的是
define([
'./a'
,
'./b'
],
function
(a, b) {
// 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})
|
seajs使用例子
1
2
3
4
5
6
7
8
9
10
11
12
|
// 定义模块 myModule.js
define(
function
(require, exports, module) {
var
$ = require(
'jquery.js'
)
$(
'div'
).addClass(
'active'
);
exports.data = 1;
});
// 加载模块
seajs.use([
'myModule.js'
],
function
(my){
var
star= my.data;
console.log(star);
//1
});
|