menu
more_vert
CMD和seaJS

作者:dayu

650) this.width=650;" src="/img/fz.gif" alt="复制代码" />

define(function(require,exports,module){//获取模块a的接口
vara=require(‘./a‘);//调用模块a的方法a.doSomething();

});

技术分享

  这个require()方法的实现和功能都特别类似于CommonJS中的require()方法。或许,有人会有疑惑,require()不是一个同步方法吗?在CommonJS中是的,在seaJS中也可以这么说,但并不完整。更合理的说法应该是,模块内的同步加载,实际表现为对模块a进行预下载

  例如下面的代码,即使不点击页面,a.js也会预先下载。点击页面后,控制台依次输出‘a‘和‘a.test‘

技术分享

//main.jsdefine(function(require,exports,module){
document.onclick=function(){vara=require(‘js/a‘);
a.test();
}
});
define(function(require,exports,module){
console.log(‘a‘);
exports.test=function(){
console.log(‘a.test‘);
}
})

技术分享

  能不能执行时再下载呢?类似于懒加载。有的,使用require.async()方法。require.async方法用来在模块内部异步加载模块,并在加载完成后执行指定回调

技术分享

//main.jsdefine(function(require,exports,module){
document.onclick=function(){
require.async(‘./a‘,function(a){
a.test();
});
}
});//a.jsdefine(function(require,exports,module){
console.log(‘a‘);
exports.test=function(){
console.log(‘a.test‘);
}
})

技术分享

【exports】

  exports是一个对象,用来向外提供模块接口。与CommonJS的exports功能类似

技术分享

define(function(require,exports){//对外提供foo属性
exports.foo=‘bar‘;//对外提供doSomething方法
exports.doSomething=function(){};

});

技术分享

  除了给exports对象增加成员,还可以使用return直接向外提供接口,这种方式与requireJS的方式类似

技术分享

define(function(require){//通过return直接提供接口
return{
foo:‘bar‘,
doSomething:function(){}
};

});

技术分享

  如果return语句是模块中的唯一代码,还可简化为

define({
foo:‘bar‘,
doSomething:function(){}
});

【module】

  module是一个对象,上面存储了与当前模块相关联的一些属性和方法

//main.jsdefine([‘./a‘],function(require,exports,module){
console.log(module);
})

技术分享

  module.uri表示根据模块系统的路径解析规则得到的模块绝对路径

  module.id是模块的唯一标识,一般情况下没有在define中手写id参数时,module.id的值就是module.uri,两者完全相同

  module.dependencies是一个数组,表示当前模块的依赖

  module.exports是当前模块对外提供的接口。传给factory构造方法的exports参数是module.exports对象的一个引用。只通过exports参数来提供接口,有时无法满足开发者的所有需求。 比如当模块的接口是某个类的实例时,需要通过module.exports来实现

  [注意]对module.exports的赋值需要同步执行,不能放在回调函数里。下面这样是不行的

技术分享

define(function(require,exports,module){//错误用法setTimeout(function(){
module.exports={a:"hello"};
},0);
});

技术分享

650) this.width=650;" src="/img/fz.gif" alt="复制代码" />

//index.html<scriptsrc="sea.js"></script>
<script>
seajs.config({
base:‘js‘
});
seajs.use("main",function(a){
a.test();
});</script>//main.jsdefine([‘./a‘],function(require,exports,module){return{
test:function(){
console.log(‘test‘);
}
}
})

技术分享

  加载多个依赖

//并发加载模块a和模块b,并在都加载完成时,执行指定回调seajs.use([‘./a‘,‘./b‘],function(a,b){
a.init();
b.init();
});

【DOMReady】

  seajs.useDOM ready事件没有任何关系。如果某些操作要确保在DOM ready后执行,需要使用jquery等类库来保证

seajs.use([‘jquery‘,‘./main‘],function($,main){
$(document).ready(function(){
main.init();
});
});

【打包】

  引入sea.js时,可以把sea.js与其他文件打包在一起,可提前合并好,或利用 combo 服务动态合并。无论哪一种方式,为了让sea.js内部能快速获取到自身路径,推荐手动加上id属性

<scriptsrc="path/to/sea.js"src="/img/fz.gif" alt="复制代码" />

<scriptsrc="sea.js"></script>
<script>
seajs.config({
base:‘js‘
});
seajs.use("main");</script>

技术分享

【别名】

  当模块标识很长时,可以使用alias来简化

技术分享

seajs.config({
alias:{‘jquery‘:‘jquery/jquery/1.10.1/jquery‘,‘app/biz‘:‘http://path/to/app/biz.js‘,
}
});

技术分享

【目录】

  当目录比较深,或需要跨目录调用模块时,可以使用paths来简化书写

技术分享

seajs.config({
paths:{‘gallery‘:‘https://a.alipayobjects.com/gallery‘,‘app‘:‘path/to/app‘,
}
});

技术分享

650) this.width=650;" src="/img/fz.gif" alt="复制代码" />

//CMDdefine(function(require,exports,module){
vara=require(‘./a‘)
a.doSomething()
//此处略去100行
varb=require(‘./b‘)//依赖可以就近书写b.doSomething()
//...})

技术分享

技术分享

//AMDdefine([‘./a‘,‘./b‘],function(a,b){//依赖必须一开始就写好a.doSomething()
//此处略去100行b.doSomething()
...
})

技术分享

  当然,AMD也支持CMD的写法,同时还支持将require作为依赖项传递

最后

  CommonJS、requireJS、seaJS这三种模块化方案,并没有高低之分。随着各个方案的不断升级,语言方面相互借鉴,使用差异逐渐变小。以上三种库级别的模块化方案,需要引入额外的库,且所遵循的规范并不是标准组织制定的,权威性不足

  随着ES6在语言层面上开始支持模块化,ES6的模块化写法才是未来的模块化标准


CMD和seaJS

原文地址:http://12945177.blog.51cto.com/12935177/1948453