CommonJs、AMD 、CMD 前端开发模块化组合


    前端模块规范:

  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
});





      前端模块化

  详解JavaScript模块化开发

  Javascript模块化编程

  从 CommonJS 到 Sea.js


你可能感兴趣的:(Web前端)