1、配置加载器
/ index.html js/ lib/ dojo/ dijit/ dojox/ my/ util/
在使用AMD模块之前我们要做的第一件事就是配置加载器,使加载器在异步模式下运行。只要将async属性值改为ture就行:
<script data-dojo-config="async: true" src="js/lib/dojo/dojo.js"></script>
我们也可以在dojoConfig对象中设置async属性,但使用任意一种方法我们都得保证这个值在loader包含到网页之前设置。如果不这样,加载器就以兼容模式的同步模式运行。
在异步模式下,加载器只会定义两个全局函数:require用来加载模块;define用来定义模块。新的加载器和旧的加载器最鲜明的对比就是旧加载器会一股脑加载Dojo Base里的所有模块,而新的加载器就不会这样做。
接下来我们要做的就是给loader配置信息,这些信息里包含我们的模块地址:
var dojoConfig = { baseUrl: "/js/",tlmSiblingOfDojo: false,packages: [ { name: "dojo",location: "lib/dojo" },{ name: "dijit",location: "lib/dijit" },{ name: "dojox",location: "lib/dojox" },{ name: "my",location: "my",main: "app" } ] };
在这个配置信息里,baseUrl设置包含所有我们JavaScript代码文件夹的地址,默认值为dojo.js所包含的那个文件夹;tlmSiblingofDojo属性被设置为false代表那些没有指定包、顶层模块的路径默认为baseUrl的地址。如果tlmSiblingofDojo默认值为true,若为true,那么认为他们和dojo包处于同一目录。这时,即使没有明确地定义until包,我们仍然调用until文件夹里的代码。
包就是模块的集合。packages包含三个主要的配置参数。name表示包的名称,实际值为包含模块的文件夹的名称;location表示包的位置,可以是一个相对于baseUrl路径或绝对路径;main是一个可选参数,表示要加载的模块,默认值为main.js,该属性可以重写,该示例中要加载的模块是app.js,该模块的确切位置是:/js/my/app.js。
2、引用模块
require函数包含下列参数:
(1)configuration:可选参数,值为对象,默认值为undefined。用来在加载器运行中修改配置
(2)dependencies:可选参数,值为数组,默认值为[],要生成模块的依赖项。
(2)callback:回调函数,你需要你的代码封装在一个回调函数,以支持异步加载和能够使用非全局引用模块。
示例一:
require( ["dojo/_base/declare","dijit/_WidgetBase","dijit/_TemplatedMixin"],function(declare,_WidgetBase,_TemplatedMixin) { // "declare" holds the dojo declare function // "_WidgetBase" holds the dijit _WidgetBase constructor // "_TemplatedMixin" holds the dijit _TemplatedMixin constructor // Do whatever you want with these modules here. });
require方法接受了一个模块标识符("dependencies")的数组,这个数组将作为它的第一参数,回调函数作为第二参数。数组里的依赖引用是有顺序的。一旦所有的依赖项准备好,它们会被按顺序传入回调函数作为函数的参数。回调函数是可选的,如果你只是想加载他们而并不想做些什么,你就可以忽略回调函数。
实例二:
require({ baseUrl: "/js/",location: "//ajax.googleapis.com/ajax/libs/dojo/1.9.2/" },location: "my" } ] },[ "my/app" ]);
在加载器运行中修改配置,它是通过将配置信息对象作为第一个参数传进去实现的。这样我们改变了配置信息,将dojo包指向了谷歌的CDN,不同于老版本模块机制,AMD机制支持隐式跨域加载,所以没有特殊的跨域版本是必要这样做的。
3、定义模块
define函数包含下列参数:
(1)moduleId:可选参数,表示模块签名,默认值为undefined,为了能够兼容旧版AMD语法,推荐不使用.
(2)dependencies:可选参数,值为数组,默认值为[],要生成模块的依赖项。
(3)factory:工厂函数,返回模块的值
// in "my/_TemplatedWidget.js" define([ "dojo/_base/declare","dijit/_TemplatedMixin" ],_TemplatedMixin){ return declare([ _WidgetBase,_TemplatedMixin ],{}); });
注意,这里我们省略了第一个可选参数:模块签名。也可以这样:return declare("my._TemplatedWidget",[ _WidgetBase,{}); 你可能会看到这样的代码,其实这样做事为了能够兼容旧版AMD语法。
在以上例子中,我们利用dojo.declare创建并返回了一份构造函数,当定义模块时一个重要的事就是工厂函数一旦被调用,加载器就会缓存它返回的值。从实践层面上来看,这就意味着模块可以依据相同的模块来轻松地共享对象。
采用旧版本Dojo编写的等效代码(不推荐使用):
dojo.provide("my._TemplatedWidget"); dojo.require("dijit._WidgetBase"); dojo.require("dijit._TemplatedMixin"); dojo.declare("my._TemplatedWidget",[ dijit._WidgetBase,dijit._TemplatedMixin ],{});
当定义模块时,值也可以作为对象:
// in "my/nls/common.js" define({ greeting: "Hello!",howAreYou: "How are you?" });
备注:如果你在定义模块是没有回调函数,你将不可能引用任何的依赖项,所以这种定义方法是罕见的。
4、使用可移植模块
dojoConfig = { packages: [ { name: "dojo16",location: "lib/dojo16" },{ name: "dijit16",location: "lib/dijit16" },{ name: "dojox16",location: "lib/dojox16" },{ name: "dojo",{ name: "myOldApp",location: "myOldApp" },location: "my" } ],map: { myOldApp: { dojo: "dojo16",dijit: "dijit16",dojox: "dojox16" } } };
如果你的应用需要使用来至两个不同版本的Dojo,新的加载器能够轻松实现。使用map配置实现这种兼容。
5、编写可移植模块
为了使加载器能够执行可移植包,任何包内的模块引用都得使用relatie标识符。
// in "my/widget/NavBar.js" define([ "dojo/dom","my/otherModule","my/widget/InfoBox" ],function(dom,otherModule,InfoBox){ // … });
使用相对模块标识符代替绝对模块标识符:
// in "my/widget/NavBar.js" define([ "dojo/dom","../otherModule","./InfoBox" ],InfoBox){ // … });
相对于"my/widget/NavBar":
"dojo/dom"在一个独立包中,使用完整标示符
"my/otherModule"是在上一个目录中,所以我们使用"../"
"my/widget/InfoBox"是在同一个目录中,所以我们使用"./"
参考文献:http://dojotoolkit.org/documentation/tutorials/1.9/modules_advanced/
http://dojotoolkit.org/documentation/tutorials/1.9/dojo_config/