您的位置:首页 > 产品设计 > UI/UE

深入浅出requireJS-1

2015-05-23 14:22 204 查看
  我们都知道,虽然我们可以通过原型和继承来使javascript面向对象。但是,当js代码和逻辑过多时,代码的维护和扩展会变的很不方便。这时,nodejs做的非常好,但是在浏览器端模块化的js编程一直都是个难题。而requireJS就是来帮助我们解决这个问题的。requireJS遵循amd规范,所以让我们先了解下关于AMD规范的事情。

一、AMD规范

  AMD规范是浏览器端的模块规范,它的全称为异步模块定义。从名称上看便知它是适合script tag的。也可以说AMD是专门为浏览器中JavaScript环境设计的规范。它吸取了CommonJS的一些优点,但又不照搬它的格式。开始AMD作为CommonJS的transport format 存在,因无法与CommonJS开发者达成一致而独立出来。它有自己的wiki讨论组

AMD设计出一个简洁的写模块API:

define(id?, dependencies?, factory);

其中:

id: 模块标识,可以省略。

dependencies: 所依赖的模块,可以省略。

factory: 模块的实现,或者一个JavaScript对象。

id遵循CommonJS Module Identifiers 。dependencies元素的顺序和factory参数一一对应。

以下是使用AMD模式开发的简单三层结构(基础库/UI层/应用层):

base.js

define(function() {
return {
mix: function(source, target) {
}
};
});


  

ui.js

define(['base'], function(base) {
return {
show: function() {
// todo with module base
}
}
});


page.js

data.js

以上同时演示了define的三种用法

定义无依赖的模块(base.js)

定义有依赖的模块(ui.js,page.js)

定义数据对象模块(data.js)

细心的会发现,还有一种没有出现,即具名模块

4,具名模块

具名模块多数时候是不推荐的,一般由打包工具合并多个模块到一个js文件中时使用。

前面提到dependencies元素的顺序和factory一一对应,其实不太严谨。AMD开始为摆脱CommonJS的束缚,开创性的提出了自己的模块风格。但后来又做了妥协,兼容了 CommonJS Modules/Wrappings 。即又可以这样写

5,包装模块

不考虑多了一层函数外,格式和Node.js是一样的:使用require获取依赖模块,使用exports导出API。

除了define外,AMD还保留一个关键字require。require 作为规范保留的全局标识符,可以实现为 module loader,也可以不实现。

目前,实现AMD的库有RequireJScurlDojobdLoadJSLocalnetNodules 等。
也有很多库支持AMD规范,即将自己作为一个模块存在,如MooToolsjQueryqwerybonzo 甚至还有 firebug
二、CMD规范
  与AMD规范类似的还有CMD规范,
在CMD中,一个模块就是一个文件,格式为:
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();

});

});

require.resolve( id )
可以使用模块内部的路径机制来返回模块路径,不会加载模块。

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 当前模块对外提供的接口。

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: