浅谈 CMD 模块化规范

概述

CMD(Common Module Definition),通用模块定义,该规范原生 js 不支持,使用 CMD 规范进行开发的时候可以引入第三方的库,即 Sea.js

定义模块

在 CMD 规范中,一个模块就是一个文件,可以通过下面的方法定义一个模块

define(factory)

参数:

参数名 是否必须 描述
factory 初始化模块需要执行的函数或对象或其他类型的值

可以发现和 AMD 模块化规范定义模块的方式是一样的,举几个常用的定义模块的例子

factory 为对象

define({ foo: "bar" });

factory 为字符串

define('My name is John Han');

factory 为函数时,默认会传入三个参数:require、exports 和 module,这点跟 AMD 模块化规范一样

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

加载模块

可以通过下面的方法加载模块,require 是 factory 函数的第一个参数

require(id)

require 是一个方法,接受模块标识作为唯一参数,用来获取其他模块提供的接口

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

还可以像下面这样异步加载模块,callback 参数可选

require.async(id, [callback])

require.async 方法用来在模块内部异步加载模块,并在加载完成后执行指定回调

define(function(require, exports, module) {
  // 异步加载一个模块
  require.async('./b', function(b) {
    b.doSomething();
  });

  // 异步加载多个模块
  require.async(['./c', './d'], function(c, d) {
    c.doSomething();
    d.doSomething();
  });
});

模块对外接口

factory 的另一个参数 exports 是一个对象,用来向外提供模块接口

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

  // 不能直接给 exports 赋值,下面的写法是错误的
  exports = {
    foo: 'bar',
    doSomething: function() {}
  };
});

除了给 exports 对象增加成员,还可以使用 return 直接向外提供接口

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

也可以使用 module.exports 向外提供接口

define(function(require, exports, module) {
  module.exports = {
    foo: 'bar',
    doSomething: function() {}
  };
});

模块系统的启动

在 Sea.js 里,通过 use 方法,可以在页面中启动模块系统

// 加载模块 main,并在加载完成时,执行指定回调
seajs.use('./main', function(main) {
  main.init();
});

use 方法还可以一次加载多个模块:

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

最佳实践:seajs.use 理论上只用于加载启动,不应该出现在 define 中的模块代码里。在模块代码里需要异步加载其他模块时,推荐使用 require.async 方法

参考链接:Sea.js官网模块的加载启动CMD模块定义规范api快速参考

除特殊说明外本人博客均属原创,转载请注明出处:http://blog.johnhan.cn/blog_1069.html
京ICP备19044523号-1