1. Dojo详解
1.1. 通用函数
1.1.1. dojo.require
在前面的示例中,其实我们已经看到了dojo.require的使用。它是用来声明将要使用的dojo的组件类型。类似Java中的import语句。
Dojo是把代码分成模块,在表现形式上是以文件目录结构存在的,类似Java的包概念。而每个模块下的Dojo类文件,就可以理解为类似Java类的概念。一般来说,Dojo中的命名规范也是类似Java的,模块(文件夹)多是小写字母;类文件以大写字母开头;属性、函数是以小写字母开头,单词间用大写字母分隔。
如果某个类是不希望被其他脚本访问的,一般以”_”作为前缀。
有时候类A的定义是放在另一个类B的文件中的,如果希望使用类A,只需要调用dojo.require(类A),就可以使用类B了。比如dijit.form.DropDownButton的定义是放在/dijit/form/Button.js中的,只要执行dojo.require("dijit.form.Button"),就可以使用它,反到是dojo.require("dijit.form.DropDownButton") 不会起什么做用的。
1.1.2. dojo.byId 和 dijit.byId
通过这两个函数的名字可以推断都是通过id来查找,它们的区别在于:dojo.byId是用来查找DOM节点,类似标准DOM的document.getElementById(id)或者IE的document.all[id];而dijit.byId是返回一个dijit的组件实例,包括dijit._Widget以及它的子类的实例。
1.1.3. dojo.addOnLoad
dojo.addOnLoad也是在之前的示例遇到过了,它把在定义在该处的脚本执行延迟到整个HTML页面加载后执行。
1.1.4. dojo.connect
dojo.connect对Dojo系统中事件响应处理很有用处,用于连接事件处理器(某一个函数)到一个元素或者一个对象,事件可以连接到任何属性或对象元素。
在之前的示例中,就是把一个函数连接到该button的onclick事件属性上去,以达到自定义事件的处理的目的。
除此之外,dojo.connect还可以实现当一个function被调用时另一个function也被调用的功能。比如:
var obj1 = {
f1: function(){
alert("hello");
}, f2: function(){
alert("world");
}
};
dojo.connect(obj1,"f1",obj1,"f2");
obj1.f1();
|
该示例的执行结果将是连续跳出两个分别显示"hello"和"world"的信息对话框。
1.1.5. dojo.forEach和dojo.query
dojo.forEach是处理循环的一个函数,第一个参数要循环的对象,第二个参数是对循环的对象内部的每一项做处理的函数。一般会和dojo.query配合使用。
dojo.query是用于选择Html中的DOM节点,第一个参数是要选择节点的特性,可以是标签名、ID和样式类中的一种,第二个参数是要选择的范围。
// 按标签名查找. 类似标准DOM的document.getElementsByTagName("IMG");不区分大小写 console.dir(dojo.query(".offToSeeTheWij")); //或者dojo.byId("widget123") |
所以经典的dojo.forEach和dojo.query配合如:
dojo.forEach( |
或者简化为
dojo.query("select",document).forEach( |
1.2. 自定义类
1.2.1. 类声明以及继承
Dojo的每个类是通过dojo.declare语句声明的,以及dojo.provide声明为可被其他外部类引用的公共类。Dojo的声明方式如下:
dojo.provide("ClassName");
dojo.declare("ClassName", SuperClassName, {
/*class body*/
});
|
需要注意的有以下几点:
1. 文件名与类名须一致。
2. "ClassName"是以字符串类型存在的,被双引号包围;SuperClassName是以对象类型存在的,没有双引号,如果该类没有父类,则SuperClassName参数赋值为null。
3. 为了避免命名冲突,类名前加以模块名,即为全路径。形似dijit.form.Button,表明是定义在根目录/dijit/form/下的Button.js文件。
4. 在类定义体内,可以定义若干变量和方法,定义之间用逗号分隔。类似:
v1: ""
,v2:null, ,constructor : function(){
}
,f1 : function(name){
alert("Hello "+name);
}
|
其中比较特殊的一个函数,名为constructor,是该类的构造函数,在用new操作创建新对象时被调用。
1.2.2. 类放置路径
一般来说,自定义的类放在自定义的模块内,这样的话易于管理,可以与Dojo的标准库代码分离。有两种方式:
1. 其中最简单的方式就是直接在Dojo根目录下,即与dojo,dijit平行的目录下,建立我们自己的模块(目录)结构,比如com/ibm/app,在该目录下创建类文件,比如ClassA,这样在其他脚本引用的时候使用dojo.require(“com.ibm.app.ClassA”)就可以了。
2. 上述的方法毕竟还有点拖泥带水,还需要放在Dojo根目录下。还有一种更脱离Dojo目录的定义方式,就是把模块放到脱离Dojo根目录的其他路径,比如与Dojo根目录的上级目录下,即创建一个与Dojo根目录平行的目录,比如说myowndojo/com/ibm/app,只要在其他脚本使用的地方调用dojo.registerModulePath("com","../../myowndojo/com")和dojo.require(“com.ibm.app.ClassA”)即可。在dojo.registerModulePath的第二个参数中"../../"表示的是myowndojo与dojo.js文件的相对路径。
1.3. Dojo组件
1.3.1. 概念简介
所谓Dojo组件,在Dojo里的概念名称是Widget,Dojo封装的常用组件一般放在dijit目录下,所有的Dojo组件都是从dijit._Widget以及其子类继承得到的,当然也有的类从dijit._Templated,dijit._Container,dijit._Contained等多重继承的来的。
这些组件大多都有对应于Html页面的组件,比如dijit.form.Button对应button,dijit.form.ComboBox对应select等。当然也有若干组件是封装好的常用Html页面元素,比如dijit.layout.TabContainer用于标签页间切换,dijit.layout.AccordionContainer提供了类似Outlook导航面板功能,这些都极大的丰富了页面展现的能力以及降低了重新开发的需要。
1.3.2. 组件生命周期
组件的生命周期指的是某一个组件从创建到销毁的存续阶段。理解在各个阶段被调用的函数有助于自定义组件或继承组件的功能扩展。
l constructor():
构造函数,在使用new操作时被调用,发生在参数被混合进组件实例之前,主要用于状态、属性的初始化。
l 参数被混合进组件实例:
如果使用标签化实现或编程实现来实例化一个组件类的时候,传入参数,比如<button dojoType="dijit.form.Button" iconClass ="">或new dijit.form.Button({iconClass: ""}),该阶段没有关联特殊的函数,但我们可以使用传入的这些参数值。
l postMixInProperties():
该函数会在该组件对应DOM节点创建前被调用。如果希望在展现前增加或修改实例的属性可以在子类里override它。
l buildRendering():
在dijit._Templated里提供的一个默认函数,用于处理组件涉及到的模板文件或模板定义串的展现。比如,在Dojo模板中,会有dojoAttachPoint这样的属性定义需要被传值,该属性的处理就是在buildRendering中。如果希望使用一套自定义的模板系统的解析,可以考虑对该函数的覆盖。
l postCreate():
被自定义组件经常使用的一个函数。执行该函数时,组件实例已经展现完成,但是请注意在containerNode下的内容还没有实现。这是构建组件的最后一个可被覆盖的函数。
l startup():
在建立了一个父组件后,还需要添加若干子组件(这里的子组件不是表示继承关系,而是表示包含关系),并希望全部加载后一起展现时,就可以调用该函数。
一个关于该函数的最佳实践就是即使没有子组件,也对一个组件新建实例调用该函数,
l destroy():
组件实例的销毁,占用资源的释放。包括该组件的DOM节点,类似C语言里的析构函数。dijit._Widget提供了多个以destroy为前缀的方法,如destroyRecursive()用于某组件以及其内部包含的子组件(这里的子组件含义同startup处的说明)的销毁。
小提示:
在某个函数需要覆盖的所有情况下,都继承执行父类的该函数,形如:
postCreate: function() { |
1.4. XMLHttpRequest(XHR)
XMLHTTP request对象是Ajax请求/响应交互中一个基础的概念,不必刷新页面就可以取回后台数据。Dojo提供了一系列封装的函数,提供统一的API实现Ajax的异步交互功能。一些比较重要的函数是dojo.xhrXXX格式的Http方法调用(此处的XXX可以是Get,Post,Put,Delete),下面以dojo.xhrGet为例进行分析。
dojo.xhrGet( {
url: "../data.json",//(1)
handleAs: "json", //(2)
timeout: 5000,//(3)
// The LOAD function will be called on a successful response.
load: function(responSEObject,ioArgs) { //(4)
return responSEObject;
},
// The ERROR function will be called in an error case.
error: function(response,ioArgs) { // (5)
console.error("HTTP status code: ",ioArgs.xhr.status);
return response; }
});
|
(1)url,表示请求的地址,可以是文件,也可以请求流;
(2) handleAs,表示处理格式,这里的值是"json",表示处理的是json格式,还有一种是text格式;
(3) timeout,以毫秒为单位,表示请求的持续时间;
(4) load()函数,第一参数responSEObject表示通过请求得到的json转换成的对象格式。换句话说,load函数是异步加载并得到数据后的执行。