来源:http://blog.csdn.net/dojotoolkit
dojo.hitch
dojo.hitch是一个优雅的函数。它会返回一个在指定作用域下执行指定语句的函数。通过调用这个函数,你可以很好地控制函数地执行,特别是在涉及到异步操作的时候。 比如下面的例子:
[javascript] view plain copy
- var myObj = {
- foo: "bar",
- method: function(someArg){
- console.log(this.foo+" "+data);
- }
- };
- dojo.xhrGet({
- url: "/something.php",
- load: myObj.method
- });
上面的例子无法正确的运行。你只会得到一个语义模糊的错误提示,比如: foo是一些变量未定义的错误。原因是,在如上例这样异步的回调函数中,当你赋给它一个关联表的时候,你改变了 ”foo”的作用域 .它的作用域不再关联到最初生成它的对象, xhr的参数对象上。要解决这个问题,你可以使用 hitch来强制这个函数保留它原来的作用域。正确的写法应该是像这样:
[javascript] view plain copy
- var myObj = {
- foo: "bar",
- method: function(data){
- console.log(this.foo+" "+data);
- }
- };
- dojo.xhrGet({
- url: "/something.php",
- load: dojo.hitch(myObj, "method")
- });
dojo.hitch需要两个参数,第一个参数指明了函数调用的关联作用域,第二个参数为一个函数对象或第一个对象中的成员函数名。
(注:关于 dojo.xhrGet,请参见后续的 AjaxIO部分)
dojo.partial
你是否想过要控制传递给函数的参数?举例来说,你是否有过这样的需求,设定传递给函数的第一个参数为已定义的值,而其它的参数仍然是可变化的。 dojo提供了一种方式可以满足这种需求。和 dojo.hitch类似, dojo.partial也是一个返回值为函数的函数。它所做的是让你可以用预定义的值锁定函数的前几个参数。这是一个非常强大的功能,特别是当你需要传入对象引用或者其它类似的给数据存储的通知函数。
下面就是一个使用 partial的示例:
[javascript] view plain copy
- var dataLoaded = function(someFirstParam, data, ioargs){};
- var args = {
- url: "foo",
- load: dataLoaded
- };
- dojo.xhrGet(args);
那么,当 xhrGet函数返回的时候它会调用 dataLoaded函数 ,但是 xhrGet的 load函数期待的参数结构应该是: load(data, ioargs)。那么在 dataLoaded的第一个参数已经确定为 "someFirstParam"的情况下,我们如何去保证 xhrGet对于参数的要求能得到满足 ?对,使用 dojo.partial!看看你可以如何用 dojo.partial来做:
[javascript] view plain copy
- var dataLoaded = function(someFirstParam, data, ioargs){};
- var args = {
- url: "foo",
- load: dojo.partial(dataLoaded, "firstValue");
- };
- dojo.xhrGet(args);
它所做的是创建一个新的函数,这个函数封装了 dataLoaded函数并且指定了第一个参数 "firstValue"。需要注意的是, dojo.partial允许你指定多个参数,因此你可以定义任意数量的参数作为函数固定前置的参数。
dojo.require
如果你想使用Dojo作为你的开发工具包,那么dojo.require是你必须要熟练掌握的。Dojo采用了与Java语言类似的命名空间(namespace)、包(package)机制,Dojo的代码都被切分为各个模块存储在各个的包中,如果你需要用到Dojo中的某个模块,那么就需要首先调用dojo.require("modulename")来预先加载该模块,否则的话,script将会抛错提示"dojo.some not defined"。
dojo.require接收一个字符串参数,该参数为要进行加载的模块名。下面是一个简单的示例:
[javascript] view plain copy
- // 加载dojo/fx.js:
- dojo.require("dojo.fx");
- // 加载dojox/widget/Toaster.js:
- dojo.require("dojox.widget.Toaster");
另外,由于各个模块之间有相互依赖性存在,用户想逐个判断并加载所有需要的模块是件很困难的事情,因此,dojo.require也提供了一些很不错的特性:
- 自动载入所有依赖的模块:
例如, dijit.form.NumberTextBox 需要引用 dojo.number ,那么当你使用dijit.form.NumberTextBox时,则不需要再次声明引用dojo.number模块。
- 预防多次载入:
当某个模块已经载入,再次声明引用相同模块,dojo.require会直接返回,而不会再次加载相同的模块。
- 通过自定义打包机制快速载入所需模块:
用户可以通过dojo提供的打包机制构建定制化的dojo包,以快速载入模块。你可以通过定制化将会多次使用的模块预加载到dojo中,而由于dojo.require()的预防多次加载机制,你也不需要对代码进行修改。
那么你可能会问,那我是不是需要通过require机制来先载入dojo.require呢?答案当然是不。顶层dojo包中的所有函数都是自动加载的(如dojo.query(),dojo.byId(),等等)。这些都是dojo的核心方法,都会在dojo引用中被频繁使用。就如同Java中的java.lang包,无需显式声明加载。
dojo.provide
与dojo.require相对应,dojo.provide是用于提供dojo模块名的函数。每一个Dojo类都必须在源代码文件开始处提供至少一个dojo.provide(),并和文件名相匹配. 例如在"Js/dojo/foo.js"文件中,在调用任何"dojo.require()"前 必须先添加 "dojo.provide('dojo.foo');" 。
下面的代码示例假设对应 my/module.js 源文件,请注意dojo.provide的调用始终在dojo.require之前。
[javascript] view plain copy
- dojo.provide("my.module");
- dojo.require("dojo.io.script");
- //dojo.provide 确保 my.module被创建为JavaScript对象以方便的进行属性赋值
- my.module.name = "my module";
注意,同一个文件中可以有多个dojo.provide,但在build脚本中一般只使用一个dojo.privide()以正确匹配文件名。
dojo.declare
JavaScript和Java不一样,它没有一个类系统,但是Dojo提供了一套模拟Java的类系统的机制:dojo.declare。
dojo.declare 接受如下的三个参数:
className: 字符串,可以为null,声明的类的名称,这个类名会被用作创建的构造子的全局名称,如果不指明名称,该类将被认为是匿名的(从V1.4开始),如果指明了名称,那么名字会被存储在创建的原型的属性”declaredClass” 中。
superclass:一个对象或对象数组,也可以为null(没有基类),声明了该类的基类,当为该参数为数组时,说明该类有多个基类。
props:一个对象,此对象所有的属性将混入到被创建的原型中。
另外,通过将一个属性命名为”constructor”,你可以为创建的对象实例增加一个初始化函数。
例子:
[javascript] view plain copy
- dojo.declare("my.Thinger", null, {
- constructor: function(/* Object */args){
- dojo.safeMixin(this, args);
- }
- });
这里我们声明了一个不继承任何类的简单的类,名为 my.Thinger 。该类最终含有一个名为 constructor 的构造函数。
你可以这样创建一个 my.Thinger 实例:
[javascript] view plain copy
- dojo.declare("my.Thinger", null, {
- count: 100,
- constructor: function(args){
- dojo.safeMixin(this, args);
- }
- });
- var thing1 = new my.Thinger();
- var thing2 = new my.Thinger({ count:200 });
- console.log(thing1.count, thing2.count);
dojo.mixin
dojo.mixin用于将对象混合在一起。所谓mixin(混入)是将两个对象从右到左组合起来,覆盖最左边的对象,并且返回混入后的对象给用户。Dojo的这个mixin非常类似于 dojo.extend ,但它只能用于对象,而不像extend显式地扩展一个对象的原型(object.prototype)。
mixin函数修改的是列表中第一个对象,将第二个对象(及以后所有对象)混入到第一个对象中。
[javascript] view plain copy
- var a = { b:"c", d:"e" };
- dojo.mixin(a, { d:"f", g:"h" });
- console.log(a); // b:c, d:f, g:h
如果您希望创建一个全新的混合对象,有如下几种做法:第一种,用dojo.clone克隆现有对象,然后再混入:
- var newObject = dojo.mixin(dojo.clone(a), b);
另一种做法是,可以用一个空对象作为第一个参数,然后将其他对象混入到这个空对象里面。您可以不断重复这个过程:
[javascript] view plain copy
- var newObject = dojo.mixin({}, b);
- dojo.mixin(newObject, c);
- dojo.mixin(newObject, dojo.mixin(e, f));
- // 可以继续不断混入
只要记住作为第一个参数的对象实例总是会被改写,并且越右面的对象,其优先级越高。
dojo.extend
dojo extend 的工作原理十分类似 dojo.mixin, 区别在于它会直接作用于一个对象的原型(prototype)之上。和mixin一样,dojo.extend将其参数最右侧的对象的成员直接合并进入第一个参数的对象。
我们可以利用extend方法来扩展一个现有类的功能:
[javascript] view plain copy
- dojo.require("dijit.TitlePane");
- dojo.extend(dijit.TitlePane, {
- randomAttribute:"value"
- });
dojo.exists
dojo.exists用于检查一个字符串中利用点号’.’分隔的所有对象是否存在, 例如 A.B.C 。dojo.exists 是一个很方便的方法,特别是在需要检测一个较长的对象路径时。它接受一个字符串作为它的第一个参数,该方法将试图沿着此字符串所表示的路径去检测此路径上所含的对象是否存在。第二个参数是可选的,可以设定一个对象作为前面所设的字符串所表示的路径的根。如果忽略第二个参数,则它将会默认使用全局对象作为根来进行检索。字符串中每个被’.’分隔的部分都会被检测是否定义过,只有当该路径上所有对象都存在时此方法才会返回true。
dojo.exists 的第一个参数是一个字符串表示要检测的对象路径,第二个参数是可选参数,是作为搜索该对象路径的根对象。返回值为一个boolean值。
[c-sharp] view plain copy
- // 检测一个控件是否存在
- var widgetType = "form.Button";
- var myNamespace = docs;
- if( dojo.exists(widgetType, myNamespace) ){
- console.log( "There's a docs.form.Button available");
- }else if( dojo.exists(widgetType, dijit) ){
- console.log( "Dijits form.Button class is available");
- }else{
- console.log( "No form.Button classes are available");
- }
dojo.clone
用于克隆对象或DOM节点,该函数返回一个克隆后的新对象。
[javascript] view plain copy
- // 克隆对象
- var obj = { a:"b", c:"d" };
- var thing = dojo.clone(obj);
- // 克隆数组
- var newarray = dojo.clone(["a","b","c"]);
dojo.addOnLoad
如果想用好dojo,必须熟悉Dojo.addOnLoad,它提供了一种机制使作为参数传入该函数的语句及其他函数可以在整个页面的DOM加载完成之后运行。常见的一种情况是:
[javascript] view plain copy
- <mce:script type="text/javascript"><!--
- if(dayOfWeek == "Sunday"){
- document.musicPrefs.other.value = "Afrobeat";
- }
- // --></mce:script>
- <form name="musicPrefs">
- <input type="text" name="other">
- .
这段JS代码会无法正确运行,因为在js运行时,”other”还未被定义。当然,你可以把这段JS代码放在页面最后,但这样做并不符合正常的HTML编写方式,而且在另一些情况下,也会对你的代码造成部分影响。
对于这类情况,你就可以使用dojo.addOnLoad(...):
[javascript] view plain copy
- function setAfrobeat(){
- document.musicPrefs.other.value="Afrobeat";
- }
- dojo.addOnLoad(setAfrobeat);
或者:
[javascript] view plain copy
- dojo.addOnLoad(
- function(){
- document.musicPrefs.other.value="Afrobeat";
- }
- );
dojo.addOnUnload
与dojo.addOnLoad(...)相呼应,Dojo.addOnUnload用于注册函数在页面销毁时运行。
[javascript] view plain copy
- <mce:script type="text/javascript"><!--
- // 声明一个在window.unLoad时运行的函数
- var unLoad = function() {
- // 函数内容
- alert("unloading...");
- }
- // 向addOnUnload传递该函数指针
- dojo.addOnUnload(unLoad);
- // 注册另一个对象的方法
- dojo.addOnUnload(window, "unLoad");
- // 注册某一对象的匿名函数
- dojo.addOnUnload(window, function() {alert("we're out of here!");});
- // --></mce:script>
dojo.query
在进行DOM相关操作时,很多时候需要查找特定的DOM节点,使用浏览器原生的DOM API进行查找不仅需要写较多的代码,而且很多时候效率十分低下,dojo.query则提供了一个更快、更方便的方式来对DOM节点进行查询。
Dojo.query接收两个参数,第一个为一个字符串,是通过一些基于CSS3标准的属性查询模板,第二个参数为可选参数,为一个DOM节点对象或节点ID,为查询设定范围。
由于dojo.query采用的是CSS3标准查询模板,当你想用dojo.query进行DOM查询时,你可以在任何的CSS文档中找到正确的查询条件模板,下面的示例是一些简单的查询调用:
[javascript] view plain copy
- // 获取所有的 <h3> 节点元素
- dojo.query('h3')
- // 获取所有为其父节点的第一个子节点的 <h3> 节点元素
- dojo.query('h3:first-child')
- // 获取id="main"的节点元素
- dojo.query('#main')
- // 获取所有id="main"的 <h3> 节点元素
- dojo.query('#main h3')
- // 获取id="main"的 <div> 节点元素
- dojo.query('div#main')
- // 获取所有在div内且id="main"的 <h3> 节点元素
- dojo.query('div#main h3')
- // 获取所有带有一个<div>子节点且在一个id="main"节点内的<h3>节点元素
- dojo.query('#main div > h3')
- // 获取所有class="foo"的节点元素
- dojo.query('.foo')
- // 获取所有class为"foo"和"bar"的节点元素
- dojo.query('.foo.bar')
dojo.byId,dojo.doc, dojo.body
dojo.byId用途与document.getElementById一致:根据DOM节点的ID返回DOM节点对象,但简短了许多,在所有的浏览器下都是有效的。
dojo.doc相当于windows[“document”]的值,该函数的作用主要有两个。首先它提供了一个指向当前文档对象的更为简洁的引用。其次,所有使用 dojo.doc 的引用,只需要通过改变dojo.doc变量的值,就可以临时切换到其它的文档对象作用域上。使用这个变量来替代对 window.document 的使用。通过这种方式可以确保是在当前页面的文档对象上工作。另外,通过使用此变量,当文档对象发生改变的时候,与文档对象相关的操作还能正确执行。这点对于需要在iframe中运行的Dijit组件来说尤为重要。
dojo.body用于返回当前文档的body对象。
dojo.create,dojo.place
dojo.create()可以简化在维护DOM时经常需要频繁执行的一系列操作步骤,例如: 新建DOM节点/给已存在的节点赋予新的属性 –> 为其设置属性 -> 将其置于DOM树上。
该函数接受四个参数: dojo.create(tag, attrs, refNode, pos);
tag可以是字符串或DOM节点。如果是字符串,函数会将其视作节点的标签名,以此来新建节点。建立节点时,会以refNode作为父节点。如果refNode为null或并未指定,则默认以dojo.doc作为父节点。
attrs是一个JavaScript对象,其中包含了用以赋予节点的一组属性信息。该参数会在节点创建成功后被原封不动的传给dojo.attr。attrs参数可以null,也可以不指定,亦即“不设置任何属性”,但是假如你想指定函数余下的传入参数,则应该为其显示的指定null值。
refNode,如之前提到的,作为创建节点的父节点对象,该参数为DOM节点对象或节点的ID。此参数可以省略,即表示“不立即安置该节点”。
pos为可选参数。取值可以是数字,或如下字符串之一:"before", "after", "replace", "only", "first", 或"last"。如果省略,则默认取"last"。表示安置创建的节点到给定的位置上。
若第一个参数传入的是``tag``字符串,则函数成功执行后会返回以该字符串命名的DOM节点,若传入的是DOM节点,则直接将其作为结果返回。例如, 新建一个带href属性的超链接标记,将其置于<body>下:
[javascript] view plain copy
- dojo.create("a", { href: "foo.html", title: "Goto FOO!", innerHTML: "link" }, dojo.body());
dojo.place函数用于放置给定的DOM节点到指定的位置上。在某些场合下,根据HTML片段来创建和安置节点也许会更容易一些,我们无需为节点设置任何属性,或是将其指定为某个HTML片段的一部分,则可以考虑使用dojo.place:
[javascript] view plain copy
- // 利用dojo.place()实现如下代码行同样的功能
- // dojo.create("a", { href: "foo.html", title: "Goto FOO!", innerHTML: "link" }, dojo.body());
- dojo.place("<a href="foo.html" mce_href="foo.html" title='Goto FOO!'>link</a>", dojo.body()
- // 利用dojo.place()实现如下代码行同样的功能
- // var n = dojo.create("div", null, dojo.body());
- var n = dojo.place("<div></div>", dojo.body());
dojo.destroy
dojo.destroy用于将当前节点从其父节点中删除,并逐一销毁自身及其所属的全部子节点。该函数仅对DOM节点有效,并且没有返回值。
[javascript] view plain copy
- // 根据id销毁节点
- dojo.destroy("someId");
dojo.attr, dojo.hasAttr, dojo.removeAttr
Dojo.attr提供了获取或修改(增加)DOM节点属性的、事件、CSS样式的方法,它既可作为getter也可作为setter。Dojo.attr包括三个参数:
[javascript] view plain copy
- dojo.attr(node, attr, value);
node:要进行操作的 DOM节点对象或其ID
attr:要进行操作的DOM节点属性名,或一个包含键值对的JSON对象,用于为DOM节点设置其中包括的所有属性
value,为可选参数,如果attr参数为某一属性名,且传入value参数,则为该节点设置相应属性,如果未传入value参数,则返回该节点的attr属性值,如果该节点没有该属性,则返回false。
dojo.hasAttr用于检查给定的DOM节点是否有给定的属性值,如果有则返回true,否则返回false:
[javascript] view plain copy
- result = dojo.hasAttr(node, attr);
dojo.removeAttr用于移除给定节点给定节点的给定属性:
[c-sharp] view plain copy
- dojo.removeAttr(node, attr);
dojo.position,dojo.marginBox, dojo.contentBox
Dojo.position用于获取给定DOM节点的绝对位置及大小信息(包括边界 - border)。返回值为一个JSON对象:{ w: 300: h: 150, x: 700, y: 900, },分别表示w:宽度,h:高度,x:X坐标值,y:Y坐标值,单位都为px。
该函数接受两个参数:
node: 要获取信息的 DOM节点对象或其ID
includeScroll:该参数为一个boolean值,默认为false,当设为true时,返回的x及y则为相对于整个document文档的位置值(忽略滚动条)。
dojo.marginBox和dojo.contentBox都可以用于获取和设置给定节点的大小,第一个参数为给定的DOM节点,第二个参数为可选参数,是一个类似于{ l: 50, t: 200, w: 300: h: 150 }的JSON对象,如果传入第二个参数,则将给定节点设置新的位置、大小。区别在于marginBox包括了节点的margin大小,它们的返回值都为一个对象:{ l: 50, t: 200, w: 300: h: 150 }。
Dojo.style
用于获取或设定DOM节点的样式。该函数接收3个参数:
- dojo.style(node, style, value);
node:要进行操作的 DOM节点对象或其ID
style:要进行操作的DOM节点样式属性名,或一个包含键值对的JSON对象,用于为DOM节点设置其中包括的所有样式
value:为可选参数,如果style参数为某一样式属性名,且传入value参数,则为该节点设置相应样式,如果未传入value参数,则返回该节点的style样式值。
dojo.hasClass, dojo.addClass, dojo.toggleClass
dojo.hasClass用于判断给定的DOM节点是否有指定的CSS class
dojo.addClass用于为给定的DOM节点增加指定的CSS class
以上两个函数都接受2个参数:
要进行操作的 DOM节点对象或其ID;一个CSS class名称字符串:
[javascript] view plain copy
- if(!dojo.hasClass("bam", "foo")){
- dojo.addClass("bam", "foo")
- }
dojo.toggleClass用于为给定的DOM节点添加或删除指定的CSS class。此函数接受3个参数:
node: 要进行操作的 DOM节点对象或其ID
class: 一个CSS class名称字符串。
condition:可选参数,为boolean值。如果给定该参数,当该 参数为TRUE时,操作为添加class,为false时操作为删除class。如果该参数未被指定,如果给定的DOM节点没有给定的class则为其添加,否则删除给定的class。
[javascript] view plain copy
- //为”example1”节点添加或删除class “style1”
- dojo.toggleClass("example1", "style1");
- //为”example2”节点添加class “style1”
- dojo.toggleClass("example2", "style2", true);