<!–markdown–>概述
CMD(通用模块定义)规范是seajs在推广中产生的产物,比起AMD规范,CMD的源生中文简直是福音啊。seajs作为一个js模块加载器(也能加载css),其基本原理离不开拼script 异步加载 js模块(文件)。其主要目的是为了解决js命名冲突、文件依赖、版本管里,还有更重要的代码维护问题。最后便是javascript模块化的另一个愿景,模块共享,通过同一个标准,使得大家的代码可以通用。
<p><!–more–></p>
加载模块
传统意加载方式,如:
<script type="text/javascript" src="http://static.hijimo.com/js/jquery1.11.1.min.js"></script>
<script type="text/javascript" src="http://hijimo.com/usr/themes/yi/js/comm.js"></script>CMD加载方式
<script src="sea-debug.js" type="text/javascript"></script>
<script type="text/javascript">
seajs.config({
base: "./js",
alias: {
'jquery':'lib/jquery1.11.1.min/jquery.js',
'haha':'app/haha',
'hehe':'app/hehe'
}
});
seajs.use(['haha'], function(haha){
//console.log('哈了悠哈');
alert(haha.obj);
});
</script>
将seajs引用到页面后,通过简单的配置后便可以使用seajs.use来动态异步加载模块,通过一个回调函数进行后续的操作。
定义模块
在引用seajs之后,我们会得到一个define函数,这个好玩的define函数不仅仅可以帮我们定义一个模块,还可以帮我们定义一个对象?
define({ "foo": "bar" });
一个字符模板?
define('I am a template. My name is {{name}}.');
又或者,一个正经的模块?
define('moduleid', [deps], function(require, exports, module) {
// 模块代码
return exports;//or reutrn {object};
});
值得注意的是,require这个参数有点小娇气,他必须书写为require,还不能被赋值,还有其他一些奇怪的要求。
其中moduleid和deps(依赖列表)是可以被省略的,具体参照官方.
seajs通过返回exports对象来向外提供模块接口。也可以直接返回对象。
exports 仅仅是 module.exports 的一个引用。在 factory 内部给 exports 重新赋值时,并不会改变 module.exports 的值。因此给 exports 赋值是无效的,不能用来更改模块接口
依赖
在上面的列子中,我的comm.js依赖于jquery.js。在传统方式中,我们必须先引用jquery后再引用comm.js(这是废话..),在实际的情况中,常常会有依赖没有被引用而造成comm.js无法正常工作的情况,特别是维护他人的项目或使用他人的组件时。
seajs(模块化)在定义模块时便将依赖引用,这样子使用者只需要知道 moduleid,并不需要管模块的依赖问题。
define(function(require, exports, module){
require('jquery');
$('#console').html('哈11哈');
return exports.obj = JSON.parse('{"obj": "123"}');
});
预加载
在seajs的配置项中有一个preload配置项,需要注意的是,他的作用可能和预想的有些出入。直接上例子
seajs.config({
base: "./js",
alias: {
'jquery':'lib/jquery1.11.1.min/jquery.js',
'haha':'app/haha',
'json':'lib/json2.js'
},
preload: [
window.JSON ? '' : 'json'
]
});
seajs.use(['haha', 'jquery'], function(haha){
//console.log('哈了悠哈');
alert(haha.obj);
});
在之前的列子(依赖)中,在haha.js中我使用了JSON库。在ie中并不包含这个库,肯定是会出错的,但是我又不想在ff,chorme的环境下引用josn2.js。为了让IE6/7/8 支持 JSON的一些API,我们会引入json2.js来修补,而在这些古老的浏览器使用JSON API必然需要预先加载好才可以继续执行。 通过preload 配置中的空字符串会被忽略掉这一约定,我们不仅可以预加载,还可以按特征检测来智能加载的,让高级浏览量无需额外的请求。
值得注意的是,seajs 中并不是读取到有preload配置就立即加载的,只能是通过 seajs.use 这个入口来触发执行预加载, 如上示例 seajs 会在执行 haha模块前确保 预加载完 JSON, 其他方式都无法保证 JSON模块已经加载并执行好
加载非CMD标准的库
一般来说官方是不建议使用seajs去加载非cmd标准的模块的。在2.1.1之前,可以通过preload 和seajs.modify的方式来加载非标准库。代码如下
seajs.config({
alias:{
'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min'
},
preload:["jquery"]
})
seajs.modify('jquery', function (require, exports, module) {
module.exports = jQuery;
});
如果非要引用的话
- 使用传统方式script引入
- 在原先类库外面包一层define,代码如下(我的jquery这些都在cdn上呀= - =)
define(function(require, exports, module){
return $;
});
- 监听事件,将对象暴露到全局(为什么不用一呢)
seajs.on('exec', function(module) {
if (module.uri === seajs.resolve('jquery')) {
window.$ = window.jQuery = module.exports
}
})