AMD

AMD规范文档:https://github.com/amdjs/amdjs-api/wiki/AMD

 

异步模块定义(Asynchronous Module Definition AMD)API 详述了一种能够保证模块及其依赖能异步加载的定义模块机制。这特别适用于浏览器环境,该环境下模块的同步加载会导致性能,可用性,调试以及跨域访问等问题。

这与科技公司AMD和它生产的处理器没有关系

 

API规范

 

define()方法

本规范只定义了一个函数‘define’,该函数对象是全局变量。函数描述为:

 

define(id?,dependencies,factory)

 

id

第一个参数,id,是一个字符串字面量。它指定了被定义模块的id。该参数是可选的,如果参数不存在,模块id应该默认为模块加载器请求的指定脚本的名字。如果存在,那么模块id必须是“顶级”或者绝对id(不允许相对id)

 

模块id格式

模块id可用于标识被定义模块,也可用于依赖数组参数。AMD中的模块id是 CommonJS Module Identifiers规范所允许的id的超集。引用该规范:

 

 一个模块id是一串由正斜杠分隔的标识名

 一个标志名必须(只能)是驼峰式标识符或“.”或“..”

 模块id不应该包含文件扩展名比如“.js”

 模块id可以是“相对的”或“顶级的”。如果一个模块id的第一个标志名是“.”或“..”,那它就是相对的

 顶级id应该从概念模块跟命名空间开始解析(?)

 相对id从“require”被书写调用的模块开始关联解析

 

以上引用的CommonJS模块id属性被经常用于JavaScript模块

 

相对模块id解析示例:

 

如果模块“a/b/c”请求“../d”,则会解析成“a/d”

如果模块“a/b/c”请求“./e”,则解析成“a/b/e”

 

依赖

第二个参数,依赖,是一个模块id数组,这些id就是当前被定义模块所需的依赖模块。这些依赖的解析必须优先于被定义模块factory方法的执行,依赖解析值应该作为参数传给factory方法,且参数位置应该跟依赖数组相对应。

依赖id可能是相对id,应该相对于当前被定义模块进行解析。换言之,相对id应该相对于模块id进行解析,而不是相对于寻找模块id的路径(?)

这个规范定义了三个拥有不同解析方式的特殊依赖名。如果“require”,“exports”或者“module”在依赖列表中出现,这个参数就应该解析成CommonJS模块规范中定义的相应的自由变量

依赖参数是可选的。如果被忽略,它应该默认为["require","exports","module"],然而,如果factory方法的arity(长度属性)小于3,那么模块加载器应该选择只以方法的arity或length属性值对应参数数量来调用这个方法

 

factory

第三个参数,factory,是一个实例化模块时应该被调用的方法或则是一个对象。如果它是一个方法,它应该只被调用一次。如果是一个对象,那它应该作为这个模块的输出值

如果factory方法返回一个值(一个对象,方法,或任意可强制类型转换为true的值),那这个值就应该作为这个模块的输出值

 

简化的CommonJS wrapping

如果依赖参数被忽略,模块加载器可以选择扫描factory方法来查找require声明形式的依赖(语法字面形式为require(“module-id”))。第一个参数必须字面上被命名为“require”来保证这个机制运行

在某些情况下,模块加载器可能因为代码大小限制或缺少方法中对toString的支持(Opera Mobile就是如此)选择不去扫描查找依赖

如果依赖参数存在,模块加载器就不应该在factory方法中查找依赖

 

define.amd属性

为了明确标识一个全局define方法(浏览器加载脚本必须的?)符合AMD规范,任何全区define方法应该有一个“amd”属性,属性值是一个对象。这有助于避免与定义了不符合AMD规范的define()方法的以及存在代码产生冲突。

这个define.amd对象的内部属性,此规范当前并无特殊规定。此规范的实现者,可以用它来实现超出本规范接口基本实现的额外能力

define.amd的存在表明遵从这个规范,如果有其他版本的API,将会类似的定义另一个属性,比如define.amd2,来标志实现遵从哪个版本的API

 

关于如何为了一个 允许在一个环节中加载多个版本模块的实现 所定义的define.amd的例子:

   define.amd = {

      multiversion:true

   };

最简定义

   define.adm = {};

 

一个传输对个模块

在一个脚本中多次调用define方法是允许的。define方法的调用顺序应该是不重要的。较早的模块定义可能指定了在同一脚本中较晚的定义作为依赖。模块加载器有责任延迟加载未解析依赖直到整个脚本加载完毕,来避免没必要的请求

 

例子

使用require和exports

创建一个名为“alpha”的模块,使用了require,exports,和名为“beta”的模块:

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
       exports.verb = function() {
           return beta.verb();
           //Or:
           return require("beta").verb();
       }
   });

 一个返回对象的匿名模块

define(["alpha"], function (alpha) {
       return {
         verb: function(){
           return alpha.verb() + 2;
         }
       };
   });

 一个没有依赖性的模块可以直接定义对象

define({
     add: function(x, y){
       return x + y;
     }
   });

 一个使用简化CommonJS转换的模块定义:

define(function (require, exports, module) {
     var a = require('a'),
         b = require('b');

     exports.action = function () {};
   });

 

全局变量

本规范保留全局变量define来实现本规范。包原信息异步定义API是为将来的CommonJS API保留的。模块加载器不应该在此函数添加额外的方法或属性

本规范保留全局变量require给模块加载器使用,模块加载器可以自由的使用这个全局变量。可以使用这个变量以及按照想要的添加任意属性或方法来实现特定功能。也可以选择不使用require变量

猜你喜欢

转载自xiaoxiaoher.iteye.com/blog/2379219
AMD