模块化开发(二)
CMD
CMD规范
CMD规范文档CMD
(Common Module Definition) 通用模块定义
。该规范明确了模块的基本书写格式和基本交互规则。该规范是在国内发展出来的。AMD是依赖关系前置,CMD是按需加载。CMD
是 SeaJS
在推广过程中对模块定义的规范化产出。
在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:1
2
3define(function(require, exports, module) {
// 模块代码
});
define方法在执行时,默认会传入三个参数:require
、exports
和 module
。如果需要一个文件中加载多个define()函数,则需要定义模块名。require
是可以把其他模块导入进来的一个参数,而export
是可以把模块内的一些属性和方法导出的。
seajs模块引入与自定义(手打RequireJS相关代码地址)
与require.js
类似,seajs
使用base
作为根目录:1
2
3
4
5
6
7
8
9
10<script type="text/javascript" src="js/sea.js"></script>
<script type="text/javascript">
seajs.config({
base:"./js",
alias:{
"range":"module/range.js"
}
})
seajs.use("app.js");
</script>
主模块加载
与require.js
不同,seajs加载模块的时候,require
函数是写在define
函数里面的,下面的例子,其实可以不用写上模块名和依赖模块(模块名要把 ID 定为文件路理由)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16define("app",["module/drag","module/scale"],function (require,exports,module){
var oInput = document.getElementById('input1');
var oDiv1 = document.getElementById('div1');
var oDiv2 = document.getElementById('div2');
var oDiv3 = document.getElementById('div3');
require("module/drag.js").drag(oDiv3);
oInput.onclick = function(){
oDiv1.style.display = "block";
require("module/scale.js").scale(oDiv1,oDiv2);
//require 是同步往下执行,require.async 则是异步回调执行。require.async 一般用来加载可延迟异步加载的模块。
require.async("module/scale.js",function(ex){
ex.scale(oDiv1,oDiv2);
})
}
})
注意,有时你想使用 require 来进行条件加载:1
2
3
4
5
6
7define(function(require){
if(false) {
require("module-A");
} else {
require("module-B");
}
});
但是,require无法完成条件加载,从静态分析的角度来看,这个模块同时依赖 module-A 和 module-B 两个模块,加载器会把这两个模块文件都下载下来。 这种情况下,推荐使用 require.async 来进行条件加载。
其实区别就是一点,require模块的加载过程是发生在模块源码分析期; require.async加载发生在模块执行期。
AMD和CMD
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
对于依赖的模块,AMD
是提前执行,CMD
是延迟执行。
AMD:提前执行(异步加载:依赖先执行)+延迟执行
CMD:延迟执行(运行到需加载,根据顺序执行)
CMD 推崇依赖就近,AMD 推崇依赖前置。看如下代码: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()
var b = require('./b') // 依赖可以就近书写
b.doSomething()
})
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
b.doSomething()
})
另外一个区别是:
AMD:API根据使用范围有区别,但使用同一个api接口
CMD:每个API的职责单一
AMD的优点是:异步并行加载,在AMD的规范下,同时异步加载是不会产生错误的。
CMD的机制则不同,这种加载方式会产生错误,如果能规范化模块内容形式,也可以
RequireJS
和 Sea.js
都是模块加载器,倡导模块化开发理念,核心价值是让 JavaScript 的模块化开发变得简单自然。
SeaJS
与RequireJS
最大的区别:
SeaJS
对模块的态度是懒执行, 而RequireJS
对模块的态度是预执行。
RequireJS的做法是并行加载所有依赖的模块, 并完成解析后, 再开始执行其他代码, 因此执行结果只会”停顿”1次, 完成整个过程是会比SeaJS要快.
而SeaJS一样是并行加载所有依赖的模块, 但不会立即执行模块, 等到真正需要(require)的时候才开始解析, 这里耗费了时间, 所以说的SeaJS是”懒执行”.