1、DOJO 快速入门-为什么是 dojo?dojo Toolkit 是一个开源的 JavaScript 工具包用于构造 web 应用。它通过提供设计良好的 api 和工具包缩短了实现设计的时间。它是轻量极其健壮的,提供工具来实现 DOM 操作,动画,ajax,event 和键盘标准化, 国际化 I18N,可访问性(a11y).Dojo 基本上是单独一个轻量级的实体(26kb). Dojo 是完全免费的,又一组活跃于社区的 developer 开发。无论项目的大小,Dojo 都是一个弹性的解决方案。内建的 package 系统不再使查找依赖成为问题,build系统合并优化各层的代码,D.O.H 使
2、单元和回归测试很容易。Add-ons除了 dojo.js 提供的大量工具,通过调用 dojo.require(),使用强大的 package 系统可以为系统增加很多功能。Dojo 核心包括 drag两个例子有同样的效果:以 debug 模式装载 dojo.js,同时运行解析器。什么时候可以开始?只要 dojo.js 在 标签中被正确引用,就可以开始写一些功能代码了。不同的浏览器对于“ready“有不同的定义。 dojo.addOnLoad()是用来被触发执行其他功能代码的 dojo函数。任何可能影响 DOM 的操作都应该通过 dojo.addOnLoad()被调用执行。例如,/ a very
3、common method of loading code onLoadvar init = function()alert(“testing“);console.log(“I run after the page is ready. See this in the console“); ;dojo.addOnLoad(init);/ and/or pass an anonymous functiondojo.addOnLoad(function()console.log(“I also run, but second. “); );dojo.addOnLoad 是 Dojo 的重要方法。需要
4、记住的是: 当使用 Dojo 时候,不要设置 onLoad()方法到标签中。dojo.addOnlLoad(someFunc)可以替代和 window.onload = someFunc。不仅仅是 DojoDojo 通过 dojo.require()装载其他相关代码。这个功能允许我们使用那些不属于 Dojo.js 的 Dojo Toolkit,比如拖放功能,动画,Dijit widgets, DojoX 项目或者开发者自己的代码。比如,在模块 dijit.TitlePane 和 dijit.form.Button 的页面中,使用 TitlePane Widget 和 dijit 按钮。dojo
5、.require(“dijit.form.Button“);dojo.require(“dijit.TitlePane“);dojo.addOnLoad(function()dojo.byId(“testHeading“).innerHTML = “Were on our way!“;console.log(“onLoad fires after require() is done“); ); 每个模块都有自己的 dojo.require(),可以不用装载已有的代码。由 dojo.addOnLoad 执行的代码要等dojo.require()装载完毕才可以运行,这样保证了安全和方便。所有可用的
6、 widgets 和 module 都可以在 Dijit API 中找到或者到 dijit/tests/的文件夹中查找。在最后的例子中,添加了经常使用的方法: dojo.byId().它返回一个 domNode 通过 id 属性。dojo.byId()是一个方便的方法来访问和操作一个特定节点。在这里通过修改.innnerHtml 来改变 body的 heading 文字。如果你看到的是“Were on our way“,那么就是表明正在做 web 开发:dojo.bliss。如果遇到 errors就表明工作出了问题。大量的常规错误德及决办法都可以在 FAQ 中找到。操作 DOMDojo 提供了
7、一个函数 dojo.query().用来处理文档对象模型(DOM),其全部内容可以足够专门写一本书来介绍。以下的部分简单讲解怎样使用 dojo.query()。dojo.require(“dojo.NodeList-fx“);dojo.addOnLoad(function()/ our dom is ready, get the node:dojo.query(“#testHeading“)/ add “testClass“ to its class=“ attribute.addClass(“testClass“)/ and fade it out after 500 ms.fadeOut(
8、 delay:500 ).play(););为页面标题添加 CSS 的样式“.testClass“并且设置 background-color:red;testClass background-color:red;dojo.query()返回一个 dojo.NodeList 的实例,这是一个 dom 的节点数组。为了展示效果,我们需要增加一些内容到页面:Dojo Skeleton PageFirst linkSecond Link First paragraphSecond paragraphThird paragraph使用 dojo.query():dojo.require(“dojo.No
9、deList-fx“);dojo.addOnLoad(function()/ get each element with class=“para“dojo.query(“.para“).addClass(“testClass“).fadeOut( delay: 1000 ).play(););经过一秒钟的延迟,所有标签将会变红然后褪色。使用 dojo.NodeList 的效果看起来很明显,在以后的章节会介绍更多的相关内容。多数 dojo.query()函数链都可以用独立的函数来替代得到相同的结果。比如:dojo.query(“#testHeading“).addClass(“testClass
10、“);和dojo.addClass(“testHeading“,“testClass“)的效果就一样。事件传递我们要接触的下一个重要概念是如何进行页面交互。现在可以为标题替换文字,那么是否可以做一些更有趣的事情呢?比如,当用户点击标题时候,就替换标题文字。dojo.connect() 是一个一站式解决方案 :dojo.addOnLoad(function()var node = dojo.byId(“testHeading“);dojo.connect(node,“onclick“,function()node.innerHTML = “Ive been clicked“; ); );另一种比
11、较方法是通过使用 dojo.query()为标题替换文字:dojo.addOnLoad(function()dojo.query(“#testHeading“).style(“cursor“,“pointer“).connect(“onclick“,function()this.innerHTML = “Ive been clicked“; ); );以上示例程序增加样式.style(),当鼠标滑过标题时会变成箭头。通过简单的 css 来简化代码。所以.style()具有动态添加和去除节点样式的特点。通过 dojo.connect()可以在同一时间把 onclick 事件连接到多个节点上。当前
12、例子中 NodeList 仅有一个节点,当然也可以添加更多的节点进行测试。例如:使用规范化的事件对象 dojo.connect(),禁止页面所有链接跳转 :var disableLinks = function()dojo.query(“a“).connect(“onclick“,function(e)e.preventDefault(); / stop the eventconsole.log(clicked: ,e.target); / the node we clicked on); ;dojo.addOnLoad(disableLinks);代码 e.preventDefault()会
13、阻止需要被执行事件的发生。本例中,这个函数阻止了 click 事件。在作为参数传递时候,事件经常写成“e“或“evt“。更多关于正规化事件对象的介绍可以参考 Dojo 网站的“Event Object Book Page“.我们可以把特定对象的方法连接起来,然后在同一范围内执行。比如在 Dijit 中声明类或者构造动画的时候,会用到这个特点。下面定义一个包含若干方法的简单对象,然后通过 dojo.connect()把这些方法连接起来:var mineObj = aMethod: function() console.log(running A); , bMethod: function() c
14、onsole.log(running B); ; var otherObj = cMethod: function() console.log(running C); ; dojo.addOnLoad(function() / run bMethod() whenever aMethod() gets run dojo.connect(mineObj,“aMethod“,mineObj,“bMethod“); / run an entirely different objects method via a separate connection dojo.connect(mineObj,“bM
15、ethod“,otherObj,“cMethod“); / start chain of eventsmineObj.aMethod(); );终端会显示“running A; running B; running C“。要学习 dojo.connect()的强大功能,可以参考dojo.connect()API 或者 Dojo Book。一些特性: Dojo 动画Dojo 拥有一个强大的动画系统,带有几个预先制作好的动画。给项目中添加一些可视化的功能通常不太容易,当然其效果会给用户有趣的体验。所有的动画都使用一个“magic object“作为唯一的参数。节点:属性对于应用到动画中的 DOM
16、节点很重要。一些参数是可选的,一些是用于高级特性。通常的配置如下所示:dojo.addOnLoad(function() var animArgs = node: “testHeading“,duration: 1000, / ms to run animationdelay: 250 / ms to stall before playing;dojo.fadeOut(animArgs).play(););基本的动画:包含在 dojo.js 中的动画效果:fadeIn, fadeOut 和 animateProperty.dojo.animateProperty 是更多高级动画的基础。dojo
17、.addOnLoad(function()dojo.style(“testHeading“,“opacity“,“0“); / hide it var anim1 = dojo.fadeOut( node: “testHeading“, duration:700 );var anim2 = dojo.animateProperty(node: “testHeading“, delay: 1000,properties:/ fade back in and make text biggeropacity: end: 1 , fontSize: end:19, unit:“pt“); anim1.
18、play();anim2.play(); );可以看到,dojo.animateProperty() 可以通过 opacity 属性使标题产生淡出效果,然后同时使文字变大。可以通过类似方法使大多数 css 属性产生动画效果。在 JavaScript 中,某些属性名子类似于 font-size 和 border-top,要使用大小写组合来替代-,变成fontSize 和 borderTop。关于 FX通过基本的 animateProperty 可以做很多可视化的工作。为了减小 dojo.js 的大小,所有其他的动画和工具都打包放在了一个单独的模块:dojo.fx,通过 dojo.require(
19、)单独调用。把 dojo.fx 模块加入代码可以增加一些动画相关的方法:bine(),dojo.fx.chain(),dojo.fx.wipeIn(),dojo.fx.wipeOut()和 dojo.fx.slideTo()。dojo.require(“dojo.fx“);dojo.addOnLoad(function()/ slide the node to 75,75dojo.fx.slideTo(node:“testHeading“,top:75, left:75).play(); / and play it);dojo.fx.chain()和 bine 都很常用,它们可以并行或者顺序执
20、行动画效果,然后返回一个dojo._Animation 对象实例:dojo.require(“dojo.fx“);dojo.addOnLoad(function()var anim = dojo.fadeOut( node: “testHeading“ );var anim2 = dojo.fadeIn( node: “testHeading“ );dojo.fx.chain(anim,anim2).play();); 把 fadeIn()和 fadeOut()通常不放到一起,现在把 fadeOut()和 slideTo()通过 bine()运行在同一个 DOM 节点:dojo.require
21、(“dojo.fx“);dojo.addOnLoad(function()var anim = dojo.fadeOut( node: “testHeading“ );var anim2 = dojo.fx.slideTo( node: “testHeading“, top:75, left:75 );var result = bine(anim,anim2);result.play(); );动画事件通过 dojo.connect()方法把 dojo._Animation()一系列的事件连接起来,产生特别的效果。常用的是onEnd()和 beforeBegin()。dojo.addOnLoa
22、d(function()var anim = dojo.fadeOut( node: “testHeading“ );dojo.connect(anim,“onEnd“,function()console.log(“ the animation is done “););dojo.connect(anim,“beforeBegin“,function()console.log(“ the animation is about to start “););anim.play(););当你要把一个隐藏的节点渐进显示出来然后改变内容,以上的方法就特别有用了。dojo.addOnLoad(functi
23、on()var anim = dojo.fadeOut( node: “testHeading“ );dojo.connect(anim,“onEnd“,function()dojo.byId(“testHeading“).innerHTML = “replaced after fade!“;dojo.fadeIn( node:“testHeading“ ).play(););anim.play(););可以把事件函数作为属性传递。使用 dojo.connect()构造函数确实功能强大而且对于高级应用也更安全,但是有时 dojo.connect()不是必需的,可以把所有的内容包括在同一个函数中
24、:dojo.addOnLoad(function()var anim = dojo.fadeOut(node: “testHeading“,onEnd: function()dojo.byId(“testHeading“).innerHTML = “replaced . “;dojo.fadeIn( node: “testHeading“ ).play();).play(););关于事件的更多解释可以参考 dojo._Animation()的API。(http:/api.dojotoolkit.org/jsdoc/dojo/HEAD/dojo._Animation )animateProper
25、tydojo.animateProperty()允许我们容易的同步使 CSS 的属性产生动画效果。作为 dojo._Animation()的一员,dojo.animateProperty() 使用和其他 animations 相同的参数,除了增加了一个对象properties:我们可以给节点定义样式属性 start:和 end:,也可以选择使用 unit:属性。修改头节点的字体颜色,大小和透明度可以如下进行:dojo.addOnLoad(function()var anim = dojo.animateProperty(node:“testHeading“,duration:700,prope
26、rties: / javascript css names are camelCase (not hyphenated)fontSize: start:12, end:22, unit:“pt“ ,opacity: start:1, end:0.5 ,color: start: “#000“, end:“#FFE“ ,delay:100 / be careful of this trailing comma, it breaks IE.);anim.play(););dojo.query()动画效果dojo 提供了另外一种方便的模块 dojo.NodeList-fx(),这个模块给 dojo.
27、query()增加了新的方法,可以实现 dojo.fx()的动画效果。dojo.require(“dojo.NodeList-fx“);dojo.addOnLoad(function()dojo.query(“#testHeading“).fadeOut().play(););上面的代码产生的效果和调用 dojo.fadeOut()一样,使用 dojo.query()可以实现节点集合中的每个对象都产生动画效果。当要操作一组节点的时候,这个功能非常有用。(在这个例子中,所有的节点应该带有同样的类别 class=fadeNode)dojo.require(“dojo.NodeList-fx“);v
28、ar fadeThem = function()dojo.query(“.fadeNode“).fadeOut().play();dojo.addOnLoad(function()dojo.connect(dojo.byId(“testHeading“),“onclick“,fadeThem););和其他 dojo.query()链不同的是,NodeList-fx 方法返回一个 dojo._Animation()的对象实例,这样就可以阻止进一步的链接。Ajax:简单的数据传输Ajax 是Asynchronous JavaScript and XML的缩写,这是一种在后台发送和接受数据的技术。它
29、可以通过连接任意数目的远程资源,然后传递数据到服务器,来回的传递响应,更新网站的任何部分,而不需要刷新 web 页面。前面熟悉了一些重要的 Dojo 方法,我们在这里介绍 Ajax 的核心技术:XmlHttpRequest(或者简称 XHR)。当使用 HTTP 的动作,如 POST,GET,PUT,和 DELETE 时,Dojo 具备几种 XHR 方法。作为学习准备,我们需要一个文本文件进行传输试验。在 js/文件夹下创建 sample.txt 例子文件:I am a remote file.We used Ajax to put this textin our page.修改 skeleto
30、n.html,增加一些基本的标记和样式:#container border:1px dotted #b7b7b7;background:#ededed;width:75px;height:55px;I am some Inner Content.I am going to be replacedXHR 方法使用 dojo.Deferred()方法在后台处理 callbacks()。这部分超出了入门教程的范围,但是在实践中很重要的部分。如果想深入学习 callbacks 以及若干构造回调的方法,可以阅读 Dojo book(http:/www.dojotoolkit.org/book/ . -b
31、etween-threads-do)或者参考 dojo.Deferred()的API。获取数据第一步是 dojo.xhrGet(),这个方法返回通过 URL 进行 GET 调用的内容。 XHR 方法共享许多参数,最重要和常用的是 url:(目的地)和 handleAs:(我们如何处理返回信息)。当被请求的数据返回时,数据会被传递给我们定义好的函数 load:var init = function()var contentNode = dojo.byId(“content“);dojo.xhrGet(url: “sample.txt“,handleAs: “text“,load: functio
32、n(data,args)/ fade out the node were modifyingdojo.fadeOut(node: contentNode,onEnd: function()/ set the data, fade it back incontentNode.innerHTML = data; dojo.fadeIn(node: contentNode).play(); ).play();,/ if any error occurs, it goes here:error: function(error,args)console.warn(“error!“,error);); d
33、ojo.addOnLoad(init);你会注意到我们把以上的技术结合起来了。内容会渐变消失,由返回数据所代替,然后渐进显示出来。handle:可以替代load: 和error: ,处理成功和失败的情景:var init = function()dojo.xhrGet(url: “sample.txt“,handleAs: “text“,handle: function(data,args)if(typeof data = “error“)console.warn(“error!“);console.log(args);else/ the fade can be plugged in here
34、, toodojo.byId(“content“).innerHTML = data;);dojo.addOnLoad(init); XHR 有一些限制。最大的问题是 url:不能跨域,你不能请求一个当前主机以外的资源 (eg. url:http:/).这是一个已知的限制和常见的问题。Dojo 提供了一个被选方案dojo.io.iframe()和 dojo.io.script()来实现更多的高级应用。如果不是用 web 服务器(从本地文件系统 ),你可能会经历一些在 IE 上出现的 Ajax 问题。原因是 XHR和 IE 之间的安全限制。多数操作文件系统的例子都会工作,这里只是建议使用 web
35、 服务器来访问 dojo的资源。发送数据所有的 XHR 方法都是双向的。唯一的不同是方法,当用户使用 POST 方法时,调用 dojo.xhrPost()。把数据嵌入到请求中(不同于 dojo.xhrGet()的查询字符串)。数据可以被直接设置成传递内容的对象参数:dojo.addOnLoad(function()dojo.xhrPost(url:“submit.html“,content: “key“:“value“,“foo“:42,“bar“: “baz“ :“value“ ,load: function(data,ioargs)console.log(data);););或者更简单的通
36、过form:参数进行转化。首先在 dojo-tutorial.html 构造一个简单的 form。Name: 然后,添加一些 JavaScript 通过 dojo.connect()来提交表单。/ sumbit the form var formSubmit = function(e)/ prevent the form from actually submittinge.preventDefault(); / submit the form in the background dojo.xhrPost(url: “alternate-submit.php“,form: “mainForm“,
37、handleAs: “text“,handle: function(data,args)if(typeof data = “error“)console.warn(“error!“,args);else/ show our response console.log(data););dojo.addOnLoad(function()var theForm = dojo.byId(“mainForm“);/ another dojo.connect syntax: call a function directly dojo.connect(theForm,“onsubmit“,formSubmit
38、););e.preventDefault()在这里又被使用。表单被提交的动作通常会导致访问一个新的页面,现在我们可以通过这个方法来禁止。示范用的 alternate-submit.php 可以写成如下:“; foreach($_REQUEST as $key = $var)print “.$key.“ = “.$var.“;print “; ?对象数据从服务器获得文本信息当然不错,不过更有用的是传递 JavaScript 对象。使用handleAs:属性,我们可以改变 dojo 如何处理返回数据。构造一个新的文件 simple-object.json 来加载:foo: “bar“,name:
39、“SitePen“,aFunction: function()alert(“internal function run“); ,nested: sub: “element“,another: “subelement“我们把 xhrPost 的 url:属性指到一个新的文件,并且提供一个 handleAs:“json“的参数来把相应数据转换成我们要使用的真实对象:var postData = function()dojo.xhrPost(url: “simple-object.json“,handleAs: “json“,load: function(data,ioargs)/ success:
40、 set heading, run functiondojo.byId(“testHeading“).innerHTML += “ by: “+data.name;if(data.aFunction ;dojo.addOnLoad(postData);运行以上代码会抛出消息:需要使用json-comment-filtered 作为 handleAs:value。可以使用这个字符串替换json或者设置 djConfig 的参数 usePlainJson:true 消除这个警告信息。在下一个版本的 dojo中将要去掉json-commenting。以上内容帮助用户传递任何类型的数据从前台到后台,而不需要中断客户体验。