Dojo工具包简介

我现在在线,有事请联系~~

简述

Dojo 工具包包含了 Web 开发中的常用 JavaScript 工具。Base dojo.js 提供了绝大部分 web 开发都需要的 '必备' API,并提供秉承 "use at
will" 哲学的大量实用工具。Dojo 是完全免费的,有 AFL 和 new-BSD Open Source
License 两种 License 可选。

可以点击此处下载 Dojo,或在网页中通过<script> 标签引用:

<script type="text/javascript" charset="utf-8" src="http://ajax.googleapis.com/ajax/libs/dojo/1.2/dojo/dojo.xd.js"></script>

这 就够了!上面的代码将从 Google Ajax API Content Distribution Network(使用 edge-caching 技术从最近的镜像中下载所需的库)载入 Dojo 工具包 (写本文时的版本是1.2 )。整个 Dojo 工具包都可以从 AOL CDN 和 Google 的新 Ajax API CDN 中获取——所有的新组件、新样式和图像。

点击此处可以查看所有 Dojo 组件概述此处是 API 参考Dojo 入门指南讲解了很多关键概念。DojoCampus 是一个很好的社区——提供了大量文档、教程和示例。docs.dojocampus.org 上有 Wiki ,以后将变成官方 Dojo 在线文档。

Dojo 库的格言是 "less Magic" —— 从0.9 版本起就使用了此格言。其 API 简洁、一致性强、有合适的命名空间并高度可扩展。每一个组件都是"随心所欲使用(use at will)";每一个特性都是可选的。

关于 Dojo:

  • Dojo 是轻量级的 —— 压缩后只有26 KB ,使用高级选项可以只有6 KB
  • Dojo 的查询引擎支持所有 CSS3 选择器,设计包含前向查找 API 。
  • Dojo 支持所有的主流浏览器:Opera 9+, FF2+, Safari 3+, 和 IE6+
    • 尽管 Dijit ( Dojo 工具包UI组件) 可在 Opera 9 中运行,但 Opera 的快捷键特性使 Dijit 无法官方宣布支持,Dojo 的每次开发过程都会发布提高兼容性的补丁。
  • Dojo 在全球有很多核心开发者
  • Dojo Build 和 Package 系统自动创建优化的 JavaScript "layers"、以及内联 CSS @import 和移除注释。
  • Dojo 有 New BSD 或 AFL两种 License。
  • DojoX 提供了大量 plugins, 而且这些插件有相似的 license 和支持,如客户端图表、Graphics API,高级 IO,大量 dojo.data Stores等。
  • Dojo 不仅有很好的社区支持 (Dojo 网站,irc.freenode.net 中的 #dojo ,及 DojoCampus);Dojo 还有收费的商业支持,如 SitePen。Dojo也获得了很多主流互联网企业的支持。

Base 概述

在客户端,小小的 dojo.js 文件提供了大量功能。dojo.js 被称作 Base Dojo —— 为所有 web 开发者提供最稳定、最常用的功能。下面是 Base Dojo 的常见工具的简介(详细介绍需要非常长的文章):

dojo.addOnLoad

注册页面载入后应运行哪些函数。这其中应该包含 Dojo package 系统载入的工具包的其他组件。dojo.addOnLoad 也接收函数作为参数,如:

dojo.addOnLoad(function() { console.log("The Page is ready!") });

这是使用 DOM 的第一步。注意使用 Dojo 时不应该直接添加 onLoad 事件处理器(大部分库都不允许)。

dojo.require

载入 Dojo 模块或组件。如下面的代码载入高级动画插件和 easing 插件:

dojo.require("dojo.fx"); dojo.require("dojo.fx.easing"); dojo.addOnLoad(function() { console.log("The Page 和 all Dojo dependencies are ready!") });

不但将载入所指明的模块,系统还将载入指明模块所依赖的所有模块。所有依赖性被解析后将调用 dojo.addOnLoad

还有很多有用的 package 工具:dojo.requireIf (条件载入), dojo.provide (通知 package 系统已提供 module ,但不重新载入)。

组合使用 dojo.requiredojo.addOnLoad 可实现资源 lazy-load 。只需在你的网页中引入 base dojo.js 并在 addOnLoad 中调用 dojo.require()

// with just dojo.js, this is basically document.ready: dojo.addOnLoad(function() { // page is rendered, add extra code: dojo.require("dijit.Dialog"); dojo.addOnLoad(function() { // Dialog and all (if any) dependencies solved: var thinger = new dijit.Dialog( { title:"A Modal Dialog", href:"remote.html" }); thinger.startup(); // show it: thinger.show(); }); });

上面例子中我们引入了 dijit 命名空间。Dijit 是 Dojo 核心的可选插件。上面的例子需要一个主题以"正确显示"——后面将介绍,现在你可以通过以下语句实现:

<head> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.2.0/dijit/themes/tundra/tundra.css" /> <script type="text/javascript" charset="utf-8" src="http://ajax.googleapis.com/ajax/libs/dojo/1.2.0/dojo/dojo.xd.js" ></script> </head> <body class="tundra"> <h2>Hello, Dijit</h2> </body>

我们在网页中添加一个 CSS 文件,并设置 class="tundra" 。这将在网页中使用 'tundra' 主题。Dojo 还提供了两个默认主题 soria nihilo 。主题本质上就是一些 CSS 和图像,你也可以自己创建。

dojo.byId

这是 document.getElementById 函数的快捷方式,但在一些 getElementById 失效的地方也可以使用。dojo.byId 返回 DOM Node,可以直接操作返回结果。dojo.byId 更短更容易键入。

dojo.addOnLoad(function() { dojo.byId("someNode").innerHTML = "I just replaced the content."; });

注意上面的代码被封装在 addOnLoad 中,以防止在载入 DOM 前运行代码。

dojo.connect

此函数可关联任何 DOM 事件和任何 node 。Dojo 处理了事件的跨浏览器问题。如下面例子为 node 添加 onclick 事件处理器:

dojo.addOnLoad(function() { var node = dojo.byId("someNode"); dojo.connect(node, "onclick", function(event) { console.log("the node was clicked: ", event.target); }); });

Dojo connect 也可以连接对象。下面的例子设置每次运行 dojo.require()时都会执行定义的函数:

var handle = dojo.connect(dojo, "require", function(arg) { console.log("require() called with: ", arg) dojo.disconnect(handle); }); dojo.require("dojo.io.iframe");

dojo.connect 传递将提供给回调函数的参数。上面通过一个匿名函数演示了如何使用。对 dojo.connect 返回值调用 dojo.disconnect 可以确保监听器只被调用一次。

dojo.connect 不止可以处理 DOM 事件。所有的方法或函数都可以作为 '事件':

var myObj = { foo:"bar", baz: function(e) { console.log(this.foo); }, bam: function(e) { this.foo = "barbar"; } }; // call myObj.bam() in scope when baz() is run dojo.connect(myObj, "baz", myObj, "bam"); myObj.baz();

第三个参数 scope 设置了函数作用域。可以向上例一样传入命名函数,也可以使用匿名函数:

var myObj = { foo:"bar", baz: function(e){ console.log(this.foo); }, bam: function(e) { this.foo = "barbar"; } }; // call anon function in myObj scope when bam() is run dojo.connect(myObj, "bam", myObj, function() { // this is know as "after advice", 和 is run after bam this.foo = "otherbar"; this.baz(); }); myObj.bam();

Connect 实际使用 dojo.hitch() 以提供作用域转换功能。dojo.hitch()作用很大。

Topics: dojo.publish, dojo.subscribe

这两个函数可以方便的向匿名对象传递或从匿名对象获取信息。使用 dojo.subscribe()注册命名通道,然后可以通过对此命名通道使用 dojo.publish() 调用匿名函数。

var subscription = dojo.subscribe("/system/alerts", function(msg) { console.log(msg); }); // and later: dojo.publish("/system/alerts", ["You've been logged out"]);

这可以很方便的实现部分页面的自动更新,而不需了解此页面的其他部分。上例中将 dojo.subscribe 返回值保存在变量中,和 dojo.disconnect 类似,可调用 dojo.unsubscribe 取消注册。

var handle = dojo.subscribe("/foo/bar", function(msg) { console.log("In this example, I'll never run.") }); dojo.unsubscribe(handle); dojo.publish("/foo/bar", ["Baz"]);

Dojo API 中很多地方使用了 Topics 。如 dojo.dnd (拖拽组件) 中使用了 Topics 以通知如 "/dnd/move/start" 和 "/dnd/move/stop" 这样的匿名事件。Dijit 组件的 dijit.layout.TabContainer 也使用了 Topics 以通知 addChild, selectChild, removeChild 等事件。

数组工具

dojo.map, dojo.filter, dojo.every, dojo.some, dojo.forEach, dojo.indexOf 等等...Dojo 封装了 JavaScript 1.6 中所有数组工具,为大部分问题提供了functional approach

最常用的是 forEach,对数组中每一个元素调用函数:

var arr = ["one","two","three","four"]; dojo.forEach(arr, function(elm, index, theArray) { // elm is the item in the array: console.log(elm); // index is where in the array we are: console.log('run ', index, ' times'); // theArray is the full array, should you need a reference to it internally: console.log(elm == theArray[index]); // should return 'true' });

第三个参数 scope 是可选的,使用 dojo.hitch 将函数作用范围设置为另一个对象。

var arr = ["one","two","three","four"]; var obj = { log: function(elm) { console.log(elm); } }; dojo.forEach(arr, function(elm) {    // elm is the item in the array:    this.log(elm); }, obj);

Filter 根据函数返回值减少数组中的元素数量:

var arr = ["one","two","three","four"]; var newArr = dojo.filter(arr, function(elm, i) { // only do even numbers: return i % 2 !== 0; }); console.log(newArr);

Map 根据函数返回值创建新元素数组:

var arr = ["a","b","c","d"]; var other = ["one", "two", "three", "four"]; var newArr = dojo.map(arr, function(elm, i) { if(i % 2 == 0) { // only odds elements from a different array return other[i]; } }); console.log(newArr);

indexOflastIndexOf 返回匹配元素位置,如果没有找到匹配则返回-1:

var arr = ["one","two","three","four","five","one"]; console.log(dojo.indexOf(arr, "two")); // 1 console.log(dojo.lastIndexOf(arr, "one")); // 5 console.log(dojo.indexOf(arr, "one")); // 0 console.log(dojo.indexOf(arr, "unknown")); // -1

DOM 和 CSS 工具

dojo.place, dojo.clone, dojo.attr, dojo.style, dojo.addClass/removeClass/toggleClass, dojo.marginBox, 和 dojo.coords 是 Dojo 提供的部分 DOM 工具,其用法比JavaScript DOM 操作简单。

dojo.place 将在另一个 node 中放置 node :

// place a new <li> as the first in the ul id="miUl": var li = dojo.doc.createElement('li'); dojo.place(li, "myUl", "first"); // give it some content, too: li.innerHTML = "Hi!";

dojo.clone 克隆 node,返回新创建的 node:

var input = dojo.query(".cloneMe")[0]; dojo.query("#someButton").onclick(function(e) { // add a new <input /> every time you click on someButton dojo.clone(input); dojo.place(input, e.target, "last"); });

dojo.attr 处理所有跨浏览器的属性设置和获取:

// getter: dojo.attr("someId", "title"); // title="bar" // setter, single: dojo.attr("someId", "title", "A new Title"); // setter, multiple: dojo.attr("someId", { "tabindex": 2, // add to tab order "onclick": function(e) { // add a click event to this node } });

dojo.styledojo.attr 相似,但用于 CSS 样式:

// getter: dojo.style("someId", "height"); // setter, single: dojo.style("someId", "padding", "8px"); // setter, multiple: dojo.style("someId", { "fontSize": "14pt", "color": "#333" });

dojo.addClass, dojo.removeClass, dojo.toggleClassdojo.hasClass 用于动态修改 node 的 class="" 属性。所有的上述函数用法相同:传入字符串形式的 ID 或 DOM Node 引用,然后函数作用于 node,或添加或移除 class 名。dojo.hasClass 返回布尔值,如果 node 含有要查询的 class 名则返回 true。

下面语句可在页面中定位 node ,或设置/获取 Node 位置和大小:

// returns x, y, t, l, w, 和 h values of id="someNode" var pos = dojo.coords("someNode"); console.log(pos); // includes any potential scroll offsets in t and l values var abs = dojo.coords("someNode", true); console.log(abs); // get just the marginBox, set another node to identical size var mb = dojo.marginBox("someNode"); dojo.marginBox("otherNode", mb);

Dojo的 DOM 工具函数为常见工作提供简单易用的 API ,并解决跨浏览器带来的麻烦。

dojo.query - Dojo的 CSS3 选择器查询引擎

"获取 DOMNodes 并处理"。

大部分的 Dojo 核心 API 都封装在 dojo.query 中。也就是说,所有可用于单个 node 的 Dojo 函数也可以用于多个匹配 node。如上面的 onclick 例子也可以写成:

dojo.addOnLoad(function() { dojo.query("#someNode").connect("onclick", function(e) { console.log('the node dojo.byId("someNode") was clicked', e.target); }); });

为简化使用,也包含了对 dojo.NodeList ( dojo.query() 返回的数组)使用 .connect() 的简单写法:

dojo.query("#someNode").onclick(function(e) { console.log('the node dojo.byId("someNode") was clicked', e.target); });

所有的 DOM Level 2 事件都有简化写法:.onclick, .onmouseenter, .onmouseleave, .onmousemove, .onmouseover, .onmouseout, .onfocus, .onblur, .onkeypress, .onkeydown, .onkeyup, .onsubmit.onloaddojo.query 方法可以嵌套使用,调用后返回相同的 NodeList 对象。

dojo.addOnLoad(function() { // connect mouseenter and mouseleave functions to all div's with the class "hoverable": dojo.query("div.hoverable") .connect("onmouseenter", function(e) { dojo.style(e.target, "opacity", 1); }) .connect("onmouseout", function(e) { dojo.style(e.target, "opacity", 0.42); }) .style( { // set the initial opacity to 0.42, as if a mouseout has happened opacity: 0.42, // and the color: backgroundColor:"#ededed" }); });

扩展 dojo.query (或"创建插件") 非常容易:

dojo.extend(dojo.NodeList, { makeItRed: function() { return this.style({ color:"red" }); }, setColor: function(color) { return this.style({ color: color }); } }); // run the makeItRed function across all nodes dojo.query(".greenNodes").makeItRed(); // set the color: property of .redNodes to a greyish tone: dojo.query(".redNodes").setColor("#ededed");

有时能直接控制 Node 引用很方便。如你为 div 添加了 onclick 事件处理器,则所有 div 内的 node 都会成为 event.target(假设 event 传递到 div)。有时你想像下面那样控制 node:

dojo.query("li").forEach(function(n) { dojo.connect(n,"onclick",function(e) { if(n == e.target) { console.log('same node'); } else { console.log('bubbling up from different node'); } // ensure we only ever add the class to the LI element, regardless of target dojo.addClass(n, "beenClicked"); }); });

Dojo 既没有污染全局命名空间,也没有去抢着占用缩写符号。如果你想为常用功能创建别名或缩写,你可以自己创建。如可用匿名函数为 dojo.query 创建别名:

(function($) { $("a[href^=http://]").onclick(function(e) { // confirm all external links before leaving the page if(!confirm("Visit" + $(e.target).attr("href") + "?")) { e.preventDefault(); } }); })(dojo.query);

Dojo 源代码中常常可见下面这样代码:

(function() { var d = dojo; d.addOnLoad(function() { d.connect(d,"loaded",function() { console.log("obfuscated some"); }) }); })();

JavaScript 是非常灵活的语言。更高级的使用方法请参考 Neil Robert 在 DojoCampus 上发布的 "Creating your Own $" 一文——把所有的 Dojo 工具放到 $ 变量中。

和其他 Dojo 组件一样 dojo.query / dojo.NodeList 也秉承"随意使用"的理念。有些特别的方法没有被写入 Base dojo.js,如果你需要可以通过 dojo.require 使用:

dojo.require("dojo.NodeList-fx"); // adds Animation support to dojo.query dojo.require("dojox.fx.ext-dojo.NodeList"); // adds DojoX addon Animations to dojo.query dojo.require("dojo.NodeList-html"); // adds advanced HTML utility functions to dojo.query 

这些 package 的命名方法略有不同。‘-’表示"跨 package 操作"。如 dojo.NodeList-fxNodeList增加"fx"功能;但你无法直接调用 dojo.NodeList-fx 。这些方法被加入到 dojo.NodeList 中。dojox.fx.ext-dojo.NodeList 的意思是" DojoX FX 模块扩展 Dojo NodeList 类"。

Ajax: 传输数据

dojo.xhr 提供简单而强大的 Ajax API 。 dojo.xhr() 函数封装了以前版本的方法:dojo.xhrGet, dojo.xhrPost, dojo.xhrPutdojo.xhrDelete

dojo.xhrGet( { url:"/path/to/remote.html", load:functiondata) { dojo.byId("updateArea").innerHTML = data; } });

使用上面的 dojo.xhr 很多任务变得很简单,如通过 GET 命令从服务器中获取远程文件内容并将结果插入到 node 中(见上文),或捕获表单并通过 Ajax 将结果 POST 到服务器上:

<!-- a simple form: --> <form id="sampleForm" action="submit.php" method="POST"> <input type="text" name="username" /> <button type="submit">login</button> </form> <script type="text/javascript"> dojo.addOnLoad(function() { var form = dojo.byId("sampleForm"); // save ref to form dojo.connect(form, "onsubmit", function(e) { // connect to, and disable the submit of this form e.preventDefault(); // post the form with all it's defaults dojo.xhrPost( { form: form, load: function(data) { // set the form's HTML to be the response form.innerHTML = data; } }); }); }); </script>

简单的处理 POST 的 PHP 脚本将返回如下结果:

<?php print "You Sent:"; print_r($_POST); ?>

所有的 dojo.xhr* 方法使用 single object hash 或 property bag 作为唯一的参数,因此不再需要记住参数的顺序——只需记住常用的名称及其用途:

  • url: 目标终点。
  • handleAs: 默认为 text,允许修改回调函数处理收到数据的方式。合法的 built-in 选项有:text, javascript, json, 或 xml
  • timeout: 等待数据时间,超过此时间仍未收到数据将抛出错误。
  • load: 数据到达时调用的函数名称。数据作为第一个参数被传递给函数。
  • error: 错误处理器函数。
  • sync: 布尔值,表明 XMLHttpRequest 是被阻塞还是在后台运行。默认值是 false,表示非同步操作。
  • handle: 出现错误或者载入成功后调用的函数。传递给函数的对象要么是数据要么是 typeof "Error"。
  • form: domNode形式的提交内容 (或字符串形式的 node ID)。如上例所示,从表单 action 属性中获得 url: 参数。可以通过同时传递 form:url: 参数改变 URL。
  • content: 送给 URL 的 JSON 对象。

本文后面讲演示 dojo.hitchdojo.partial 的强大功能,可以方便的控制 load:, error:handle: 回调函数的作用域。

FX: 灵活且强大的动画 API

Base dojo.js 包含简单的 fade 方法,及强大的 animateProperty 方法(用于添加 CSS 属性动画)。所有动画方法返回 dojo._Animation 实例,使用此对象可以控制动画序列。下面代码闯并运行 fade 动画:

dojo.addOnLoad(function() { dojo.fadeOut( { node:"someNode", // a node ref, byId }).play(); });

dojo._Animation 实例有 play(), stop(), status(), gotoPercent(), 和 pause() 方法用于控制动画。除了 dojo.anim 都使用 single object hash 定义选项。一些很有用的选项包括:

var anim = dojo.fadeOut( { node: "someNode", // node to manipulate duration: 3000, // time in ms to run the animation easing: function(n) { // a linear easing function, alter the progression of the curve used return n; }, delay: 400, // time in ms to delay the animation when calling .play() rate: 10 // a framerate like modifier. }); anim.play();

可选的 dojo.fx.easing 中有超过 30个函数。使用 dojo.require() 即可使用:

dojo.require("dojo.fx.easing"); dojo.addOnLoad(function() { dojo.fadeOut( { node:"someNode", easing: dojo.fx.easing.bounceOut // bounce towards the end of the animation }).play(); });

上面的函数中也可以在动画进程中发出各种事件。下面是一个例子:

dojo.addOnLoad(function() { dojo.fadeOut( { node:"someNode", beforeBeing: function() { console.log("the animation will start after I've executed"); }, onBegin: function() { console.log('the animation just started'); }, onEnd: function() { console.log('the animation is done now'); }, onPlay: function() { console.log('the animation was started by calling play()'); }, onStop: function() { console.log('the animation was stopped'); } onAnimate: function(val) { // fired at every step of the animation console.log('current value: ', val); } }) });

最常用的事件是 onEnd。下面的代码可让某些内容渐出,然后再渐入显示通过 Ajax 获得的替代内容:

var n = dojo.byId("someNode"); dojo.fadeOut( { node: n, onEnd: function() { dojo.xhrGet( { url: "newContent.html", load: function(data) { n.innerHTML = data; dojo.fadeIn({ node: n }).play(); } }) } }).play();

node: 参数既可以是 DOM Node 引用,也可以是将传递给 dojo.byId 的字符串。下面的例子中,我们将引用存为"n"并用于回调函数:

复杂动画中可以使用 dojo.connect_Animation 实例就是要连接的对象:

// create a simple loop var fadein = dojo.fadeIn({ node: "someNode" }); var fadeOut = dojo.fadeOut({ node: "someNode" }); // call fadeout.play() anytime fadein's onEnd is fired: // and re-play fadein when fadeout's onEnd is fired: dojo.connect(fadein, "onEnd", fadeout, "play"); dojo.connect(fadeout, "onEnd", fadein, "play"); // start the loop fadeout.play();

渐入渐出特效很有用,但这只是 dojo.animateProperty 的简单封装实现的。实际是为 opacity 属性设置动画:

// simulate fadeIn dojo.animateProperty( { node:"someNode", properties: { opacity: 1 } }).play(); // as opposed to: // dojo.fadeIn({ node: "someNode" }).play();

animateProperty 更健壮更灵活。通过此函数,可以为一个 node 中的任意多个属性设置动画:

dojo.animateProperty( { node:"someNode", properties: { // end is assumed: opacity:0, // define a start and end value: marginLeft: { start:5, end:250 } // start is calculated, use unit "em" padding: { end:5, unit:"em" } } }).play();

当然所有的 dojo._Animation 事件和配置选项都有效。properties hash 接收多种格式。如同时传入 start: 值和 end: 值,node 被强制使用这些属性值。如果只传入 end: 值,则会将当前属性值作为 start: 值。如果只传入一个整数值,则此值将被视为 end: 值。unit: 参数默认为 "px",需要注意的是有些浏览器并不能正确的将 "em" 和 "pt" 值转换为像素数。

注意上面例子中的 marginLeft 。CSS 中此值将是 margin-left:,但是 JavaScript 中-是非法的。每个标准的 CSS 属性都有 JavaScript 的 camelCase 版本属性名,如 marginLeft

你可能已经注意到 animateProperty 文法比较复杂,如每个例子中都需要调用返回的 _Animation .play() 方法。Base Dojo 中存在方法以简化使用:

dojo.anim("someNode", { opacity:0, marginLeft: { start:5, end:250 }, padding: 50 });

上面的例子和以前的例子效果相同。为了方便使用 dojo.anim 而放弃了灵活性,因为现在的参数是有顺序的了。动画将自动被调用 play()方法。

高级 JavaScript 工具

Dojo 中包含 dojo.declaredojo.mixin 及 prototypical inheritance 函数 dojo.extenddojo.delegate 。还有像 dojo.hitchdojo.partial 这样的作用域操作函数。

Dojo 中最神奇的函数就是 dojo.hitch,可以创建在其他作用域中运行的函数。

var foo = function() { var bar = function(arg) { console.log("was passed: ", arg); } dojo.fadeOut( { node: "nodeById", onEnd: dojo.hitch(this,"bar") }).play(); }

这里需要注意的是 hitch 创建的函数没有被立刻执行。上例中,我们在 this 作用域中调用了一个本地函数。DojoCampus 中有几篇很好的关于 dojo.hitch 的文章,详细介绍了 Javascript 作用域操作。

dojo.partialdojo.hitch类似,不同是 dojo.partial 默认全局作用域。

var style = dojo.partial(dojo.style,"someNodeId"); // anytime we execute this function, we'll style a node with id="someNodeId" style("opacity",0.5); style("backgorundColor","#fff"); // it also acts as a getter: var val = style("width"); console.log(val);

dojo.mixin 的功能是混合多个对象:

var obj = { a: "foo", b: "bar" }; dojo.mixin(obj, { b: "baz", c: "bam" }); console.log(obj); // Object a=foo b=baz c=bam

上面的例子中删除了重复的b:

可以使用 dojo.clone (也可用于 DOM Node )创建新对象并添加属性:

var obj = { a: "foo", b: "bar" }; var newObj = dojo.clone(obj); dojo.mixin(newObj, { b: "baz", c: "bam" }); console.log(obj, newObj); // Object a=foo b=bar Object a=foo b=baz c=bam

Dojo 中使用 declare 创建类。此函数允许使用面向对象方式创建可复用的对象。下面的例子将创建 Person 类和 Person 类实例:

dojo.declare("Person", null, { constructor: function(nick, name, age) { this.nick = nick; this.name = name; this.age = age; this.location = null; }, setLocation:functionloc) { this.location = loc; }, getLocation:function) { return this.location; } }); var dante = new Person("dante","Peter Higgins", 28); dante.setLocation("Tennessee"); console.log(dante.getLocation());

可以在 declare 中创建继承类。下例中 Employee 类继承 Person 类。Employee 包含更多的数据成员:

dojo.declare("Person", null, { constructor: function(nick, name, age) { this.nick = nick; this.name = name; this.age = age; this.location = null; }, setLocation:functionloc) { this.location = loc; }, getLocation:function) { return this.location; } }); dojo.declare("Employee", Person, { employeeId: 0, setId: function(id) { this.employeeId = id; } }) // I am employed: var dante = new Employee("dante","Peter Higgins", 28); dante.setLocation("Tennessee"); dante.setId(42); console.log(dante.employeeId);

这样就可以创建 People 和 Employee,并通过属性和方法区分。

通过 dojo.mixin 可为类的实例添加自定义的属性:

dojo.declare("Person", null, { constructor: function(nick, name, age) { this.nick = nick; this.name = name; this.age = age; this.location = null; } }); var dante = new Person("dante","Peter Higgins", 28); dojo.mixin(dante, { employeeId: 42 }); console.log(dante.employeeId); // 42

使用 dojo.extend 可以直接修改类。使用 extend()后所有实例都可以使用扩展属性:

dojo.declare("Person", null, { constructor: function(nick, name, age) { this.nick = nick; this.name = name; this.age = age; this.location = null; } }); // add Eye-color functions to the Person Class dojo.extend(Person, { eyeColor:"adefault", setEyeColor: function(color) { this.eyeColor = color; } }); var dante = new Person("dante","Peter Higgins", 28); console.log(dante.eyeColor); // default dante.setEyeColor("brown"); console.log(dante.eyeColor); // brown

dojo.declare, dojo.mixindojo.extend 提供的灵活性适用于整个 Dojo 工具包。你可以尽情修改、重用、扩充 Dojo, Dijit, 及 DojoX 。如所有的 Dijit 类都继承自名为 dijit._Widget的基类。

Built-in 命名空间支持

再也不用担心代码的位置了!dojo, dijit, 和 dojox 命名空间都是同一级文件夹,位于 ../namespace (相对于 dojo/)。你可以通过创建文件夹封装你的代码并创建自定义的命名空间:

+ dojo-1.2/ + dojo/ + dojo.js + dijit/ + dojox/ + custom/ + kernel.js

只需要使用 dojo.provide()通知 Dojo 。在 dojo-1.2/custom/kernel.js中:

dojo.provide("custom.kernel"); dojo.require("dojo.io.iframe"); custom.init = function() { // comments get removed as part of the Build process console.log("I am custom code!"); } dojo.addOnLoad(custom.init);

在网页中只需要 dojo.require 你的 package:

dojo.require("custom.kernel"); 

如果想把你的代码放在 dojo-1.2 文件夹之外,只需要注册相对于 dojo.js 的路径:

+ dojo-1.2/ + dojo/ + dojo.js + dijit/ + dojox/ + custom/ + templates/ + Template.html + kernel.js

在你的 HTML 中,注册路径。上例注册代码为:

dojo.registerModulePath("custom", "http://www.cnblogs.com/custom"); dojo.require("custom.kernel"); 

最重要的就是在你的 Web 服务器中定位 dojo.js。然后一切就OK了。注册了模块路径后,就可以轻松的访问那个路径中的任意文件:

dojo.require("dijit._Widget"); dojo.require("dijit._Templated"); dojo.declare("custom.Widget", [dijit._Widget, dijit._Templated], { templatePath: dojo.moduleUrl("custom", "templates/Template.html"); });

总结

此教程粗略的介绍了如何使用 Dojo 工具包帮助开发网页。欲了解更多,请访问 Dojo 网站。Dojo 不仅有免费的社区支持 ( Dojo 网站,irc.freenode.net 中的 #dojo ,及 DojoCampus);Dojo 还有收费的商业支持,如 SitePen。Dojo 也获得了很多主流互联网企业的支持。我们希望您积极参与以帮助我们改进Dojo。

posted @ 2010-10-18 12:33  Jet J.J.Cheng  阅读(613)  评论(0编辑  收藏  举报