Dojo学习笔记(二):AMD模块高级使用

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/",
    packages: [
        { name: "dojo", location: "//ajax.googleapis.com/ajax/libs/dojo/1.9.2/" },
        { name: "my", 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/_WidgetBase", "dijit/_TemplatedMixin" ], function(declare, _WidgetBase, _TemplatedMixin){
    return declare([ _WidgetBase, _TemplatedMixin ], {});
});

   注意,这里我们省略了第一个可选参数:模块签名。也可以这样:return declare("my._TemplatedWidget", [ _WidgetBase, _TemplatedMixin ], {}); 你可能会看到这样的代码,其实这样做事为了能够兼容旧版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", location: "lib/dojo" },
        { name: "dijit", location: "lib/dijit" },
        { name: "dojox", location: "lib/dojox" },
        { name: "myOldApp", location: "myOldApp" },
        { name: "my", 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"
], function(dom, otherModule, 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/


本文出自 “IT技术学习与交流” 博客,谢绝转载!

你可能感兴趣的:(dojo,amd)