踏上前端这条道路以来,我一直以为自己就是个娴熟的切图工,每天只需要做着重复的劳动,切图,做网站。然而,技术的发展是日新月异的,切图工早就面临淘汰。随着浏览器功能越来越完善,前端项目越来越大,代码越来越复杂,为了适应这种变化,越来越要求前端开发模块化。

首先介绍一下什么是模块化。模块化是指解决某一个复杂问题,按照一种分类的思维把问题进行系统分解,并处理。譬如将巨大的系统代码,整合优化分割成高内聚低耦合的模块,达到便于管理,维护和开发的目的。

模块化设计,必须实现以下能力:

  1. 定义封装的模块
  2. 定义新模块对其他模块的以来
  3. 对其他模块的引入支持。

介绍其中最主要的两种规范,CMD和AMD。

AMD 与 RequireJS

AMD:Asynchronous Module Definition 异步模块定义 [e'sɪŋkrənəs]

AMD采用require([module],callback);加载模块,require有两个参数,一个是依赖的模块数组,一个是回调函数。目前主要有两个Javascript库实现了AMD规范,require.js和curl.js

require.js主要解决以下两个问题:

(1)实现js文件的异步加载,避免网页失去响应;

(2)管理模块之间的依赖性,便于代码的编写和维护。

require.js使用方法

(1)下载js加载入页面

(2)加载自己的代码    <script src="js/require.js" data-main="js/main"></script>

main.js 

1 require(['moduleA','moduleB'],function(moduleA,moduleB){
//code here
});
//假定主模块依赖jquery、underscore和backbone这三个模块,main.js就可以这样写:
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){ // some code here });

模块的加载

require.config();    config方法可以对模块的加载行为进行自定义。require.config()就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径,baseUrl为基目录

//main.js
require.config({ baseUrl:"js/lib", paths:{ "jquery":"jquery.min", "underscore":"underscore".min, "backbone":"backbone.min" } })

AMD模块的写法

模块必须采用特定的define()函数来定义,如果一个模块不依赖于其他模块可以直接定义在define()函数中。

假定一个math模块

  //  math.js

    define(function(){

        var add = function(x,y){

            return x+y;

         };

         return {add:add};

    });

  //  加载方法   main.js

    require(['math'],function(math){

         alert(math.add(1,1));

    });

如果这个模块依赖其他模块,define()函数的第一个参数必须是一个数组,指明该模块的依赖性

define(['myLib'],function(myLib){

    function foo(){

        myLib.func();

    }

     return {foo:foo};

});

//当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。

 require方法调用模块

require(['module1','module2'],function(module1,module2){

     module1.func();

     module2.func();

  })

//在加载 foo 与 bar 两个模块之后执行回调函数实现具体过程。

同时还可以在define定义模块内部进行require调用模块

   define( function( require ){
var m1 = require( 'module1' ),
m2 = require( 'module2' );
...
});

加载非规范的模块

在require()加载之前,先用require.config()方法,定义他们的一些特征。

require.config({

      shim:{

             'underscore':{

                     exports:'_'

                     },

              'backbone':{

                       deps:['underscore','jquery'],

                       exports:'Backbone'
} } }); /*require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义
(1)exports值(输出的变量名),表明这个模块外部调用时的名称;
(2)deps数组,表明该模块的依赖性。*/ //比如jQuery插件定义 shim:{ 'jquery.scroll':{ deps:['jquery'], exports:'jQuery.fn.scroll'
} }

CMD 与 seaJS  (转载)

CMD:Common Module Definition   通用模块加载规范

在CMS中一个模块就是一个文件,格式和AMD有些类似,define(factory);define定义模块,参数factory可以是一个函数或者对象,字符串,当factory为对象字符串时,表示模块的接口是该对象。

定义JSON数据模块:

define({"foo":"bar"});

通用字符串定义模板模块

 define('this is {{data}}!');

factory 为函数的时候,表示模块的构造方法,执行构造方法便可以得到模块向外提供的接口。

 define( function(require, exports, module) {
// 模块代码
});

define( id?, deps?, factory );

define也可以接受两个以上的参数,字符串id为模块标识,数组deps为模块依赖:

    define( 'module', ['module1', 'module2'], function( require, exports, module ){
// 模块代码
});

其与 AMD 规范用法不同。

 require 是 factory 的第一个参数。
  require( id );
  接受模块标识作为唯一的参数,用来获取其他模块提供的接口:
    define(function( require, exports ){
var a = require('./a');
a.doSomething();
});

require.async( id, callback? );

require是同步往下执行的,需要的异步加载模块可以使用 require.async 来进行加载:

    define( function(require, exports, module) {
require.async('.a', function(a){
a.doSomething();
});
});

exports 是 factory 的第二个参数,用来向外提供模块接口。

    define(function( require, exports ){
exports.foo = 'bar'; // 向外提供的属性
exports.do = function(){}; // 向外提供的方法
});

当然也可以使用 return 直接向外提供接口。

    define(function( require, exports ){
return{
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
}
});

也可以简化为直接对象字面量的形式:

    define({
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
});

与nodeJS中一样需要注意的是,一下方式是错误的:

    define(function( require, exports ){
exports = {
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
}
});

需要这么做

    define(function( require, exports, module ){
module.exports = {
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
}
});

传 入的对象引用可以添加属性,一旦赋值一个新的对象,那么值钱传递进来的对象引用就会失效了。开始之初,exports 是作为 module.exports 的一个引用存在,一切行为只有在这个引用上 factory 才得以正常运行,赋值新的对象后就会断开引用,exports就只是一个新的对象引用,对于factory来说毫无意义,就会出错。

    module 是factory的第三个参数,为一个对象,上面存储了一些与当前模块相关联的属性与方法。
        module.id 为模块的唯一标识。
        module.uri 根据模块系统的路径解析规则得到模块的绝对路径。
        module.dependencies 表示模块的依赖。
        module.exports 当前模块对外提供的接口。

seaJS

    官网 http://seajs.org/docs/
    sea.js 核心特征:
        1. 遵循CMD规范,与NodeJS般的书写模块代码。
        2. 依赖自动加载,配置清晰简洁。
        兼容 Chrome 3+,Firefox 2+,Safari 3.2+,Opera 10+,IE 5.5+。

 seajs.use  用来在页面中加载一个或者多个模块

    // 加载一个模块
seajs.use('./a');
// 加载模块,加载完成时执行回调
seajs.use('./a',function(a){
a.doSomething();
});
// 加载多个模块执行回调
seajs.use(['./a','./b'],function(a , b){
a.doSomething();
b.doSomething();
});

AMD 与 CMD 的区别

  下面是玉伯(sea.js创始人)对于 AMD 与 CMD 区别的解释:

    AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
    CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
    类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出还有不少??
    这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。
    目前这些规范的实现都能达成浏览器端模块化开发的目的。
    区别:
    1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
    2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
    // 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()
// ...
})
虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。

    3. AMD 的
API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部
require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use
来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。

    4. 还有一些细节差异,具体看这个规范的定义就好,就不多说了。
       
另外,SeaJS 和 RequireJS 的差异,可以参考:https://github.com/seajs/seajs/issues/277
扩展阅读:
前端模块化开发的价值 https://github.com/seajs/seajs/issues/547
前端模块化开发那点历史 https://github.com/seajs/seajs/issues/588
从 CommonJS 到 Sea.js https://github.com/seajs/seajs/issues/269    

RequireJS和AMD规范  http://javascript.ruanyifeng.com/tool/requirejs.html

知乎  AMD 和 CMD 的区别有哪些? http://www.zhihu.com/question/20351507

CMD和AMD探秘的更多相关文章

  1. CMD和AMD区别的概括

    CMD和AMD区别   AMD CMD 关于依赖的模块 提前执行(不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)), 延迟执行 关于依赖的位置 依赖前置 ...

  2. CMD和AMD

    CMD是国内玉伯在开发SeaJS的时候提出来的,属于CommonJS的一种规范,此外还有AMD,其对于的框架是RequireJS. 二者的异同之处: 二者都是异步(Asynchronuous Modu ...

  3. CommonJS、CMD和AMD规范分别是什么

    CommonJS.CMD和AMD规范分别是什么 Commonjs是用在服务器端的,同步的,如nodejs amd, cmd是用在浏览器端的,异步的,如requirejs和seajs 其中,amd先提出 ...

  4. CMD和AMD的区别

    CMD和AMD俩者之间的区别 AMD和CMD最大的区别是对依赖模块的执行时机处理不同 CMD和AMD都是CommonJS延伸而来的,CommonJS是随着node的出现而出现的,它是一个规范,用于定义 ...

  5. 转: cmd和amd的区别

    AMD 规范在这里:https://github.com/amdjs/amdjs-api/wiki/AMDCMD 规范在这里:https://github.com/seajs/seajs/issues ...

  6. 两句话概括cmd和amd的区别

    === | === | === | ===AMD | 速度快 | 会浪费资源 | 预先加载所有的依赖,直到使用的时候才执行=== | === | === | ===CMD | 只有真正需要才加载依赖 ...

  7. 模块化规范:CMD和AMD的区别

    https://www.zhihu.com/question/20351507/answer/14859415 AMD(异步模块定义) 是 RequireJS 在推广过程中对模块定义的规范化产出.CM ...

  8. CMD与AMD区别

  9. 研究一下javascript的模块规范(CommonJs/AMD/CMD)

    最近写react需要使用nodejs作为开发环境,需要通过npm安装一些第三方的依赖库,因此慢慢感觉到nodejs基础薄弱对我带来了一些不安全感,尤其是javascript模块这一块听到了很多概念,比 ...

随机推荐

  1. 成为Java顶尖高手要看的11本书

    成为Java顶尖高手要看的11本书 学习的最好途径就是看书",这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 1.能出版出来的书一定是经过反复的思考.雕琢和审核的 ...

  2. visual studio运行时库MT、MTd、MD、MDd的研究(转载)

    转载:http://blog.csdn.net/ybxuwei/article/details/9095067 转载:http://blog.sina.com.cn/s/blog_624485f701 ...

  3. 自动布局(Masonry)设置tabbar

    //自定义标签工具栏 - (void) initTabBarView{ // self.bottomView = [[UIView alloc]initWithFrame:CGRectMake(, k ...

  4. mysql 用sql语句查询一个表中的所有字段类型、注释

    SELECT column_name,column_comment,data_type FROM information_schema.columns WHERE table_name='表名' AN ...

  5. SqlSever基础 print 在消息中输出hello world

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  6. NTT

    1 问题描述FFT问题解决的是复数域上的卷积.如果现在的问题是这样:给出两个整数数列$Ai,Bj,0\leq i\leq n-1,0\leq j\leq m-1$,以及素数$P$,计算新数列$Ci=( ...

  7. iOS日常工作之常用宏定义大全

    前言: 在工作中, 很多小伙伴都会在PCH文件定义一些常用的宏,但是又怕写这些简单的宏浪费时间,又有时候忘记怎么定义了怎么办?本人在工作中也是如此.所以在这里给大家分享一些常用的宏定义,喜欢的小伙伴可 ...

  8. 主框架搭建demo

    - (void)viewDidLoad {     [super viewDidLoad];        [self setUpAllChildViewController]; }    /**   ...

  9. VPython—旋转坐标系

    使用arrow( )创建三个坐标轴代表一个坐标系,其中X0-Y0-Z0为参考坐标系(固定不动),X-Y-Z为运动坐标系,这两个坐标系原点重合,运动坐标系可以绕参考坐标系或其自身旋转.在屏幕上输出一个转 ...

  10. 即时定位与地图构建SLAM(Simultaneous Localization and Mapping)

    SLAM 即时定位与地图构建SLAM(Simultaneous Localization and Mapping) 参考链接: 视觉SLAM漫谈,http://www.cnblogs.com/gaox ...