全称为Asynchronous Module Definition,异步组件(或模块)定义。AMD是一种机制,使用这种机制,组件和它的依赖就可以实现异步加载。
Define方法
define(id?, dependencies?, factory);
组件ID
组件ID是组件的唯一标识符,在和组件ID一对一的脚本文件(一个脚本文件中只有一个define)中这个ID可以没有,而且最好没有。这是因为组件加载器在请求组件的时候是必须给一个组件ID的,而且需要配置组件ID对应的脚本文件路径。加载器根据文件路径就能找到对应的组件脚本文件。所以,加载器可以直接用请求时使用的ID作为这个组件的ID。这样的好处是组件转移到其它项目的时候不需要怕ID冲突而需要修改组件ID,所以,使用define方法定义组件的时候,最好不要设置组件ID。
而且,根据AMD规范,define方法的第一个参数,组件ID必须是顶级或绝对ID,不能是相对ID。这更容易导致组件ID冲突所以,所以,我认为更不应该在define方法中设置组件ID。
AMD认为使用define可以帮助静态分析工具,比如build,我觉得没这个必要,因为更多时候在define中组件ID都没有,分析没有意义。
根据AMD规范,一个文件中定义多个组件也是可以的,但这就必须给每个define分配一个组件ID。
组件ID格式
注意,在define方法中出现的组件ID必须是顶级或绝对ID。但在require方法或define的依赖数组中出现的组件ID,可以是相对ID(相对于当前组件的ID,而不是相对于组件的路径),并且完全兼容CommonJS关于组件ID格式的规范。
CommonJS关于组件ID的约定:
l 组件ID由‘/‘分隔的词组成,每个词必须是驼峰式写法,也可以是‘.‘、‘..‘,用于表示相对关系;
l 组件ID可以有‘.js‘后缀,也可以没有‘.js‘后缀;
举例:
假如组件‘jquery/dialog‘对应路径‘jquery/ui/dialog.js‘,而它依赖‘jquery/jquery.js‘,就需要在‘dialog.js‘文件中把require写成这样:require( ‘../jquery‘)或require(‘../jquery.js‘)。
依赖数组
也就是第二个数组,依赖数组包含依赖的组件ID,这里的组件ID允许相对ID。如果没有定义依赖数组,理论上默认是[‘require‘,‘exports‘,‘module‘],但这可以取决于factory这个方法的参数个数。如果参数只有一个,那么依赖数组就可以只是[‘require‘],其它两个依此类推。
Factory
如果factory是个方法,它的返回值就是该组件对外开发的值。如果factory是个对象,那么factory就是对外开放的值。
Define.amd
这个属性是个object,有这个属性就表示这个全局的define方法符合AMD规范。至于amd有什么属性,AMD没有规定,可以根据情况自己写。
Require方法
AMD对于require方法的要求比define低,组件加载器可以随意发挥,只要保证能正常工作即可。比如requirejs的require方法就可以一次要求多个组件,而根据CommonJS规范的组件加载器一次只能要求一个组件。
CommonJS
根据CommonJS的指导,CommonJS是没有define方法的,依赖完全通过require(‘module-id‘)获取。好在在浏览器中,Function对象有一个toString()方法,可以把方法转换成文本格式。通过在文本中搜索require(‘module-id‘)就可以获取所有依赖。缺点就是这样就失去了根据条件加载依赖的能力,而是一股脑全部加载。
AMD通过define方法声明模块,CommonJS是没有define方法的,所以AMD和CommonJS是两回事。但是,根据define的第二个参数的要求,可以看出,AMD的组件同样可以有require、exports、module这三个变量,因此,把CommonJS组件的代码拷贝到define方法中,大部分代码不用修改就可以用的,这点还是比较方便。
注意:Opera手机平台的Function对象没有toString()方法,因此CommonJS格式的脚本在这个平台上可以不能正常运行。