﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-The NoteBook of EricKong-随笔分类-dojo</title><link>http://www.blogjava.net/jjshcc/category/54519.html</link><description>桑巴葡语翻译工作室是广州市最专业葡萄牙语翻译机构-www.puyufanyi.com-欢迎寻找Java,As400,Mainframe的猎头eric_cc#qq.ccom(把#换成@)</description><language>zh-cn</language><lastBuildDate>Wed, 11 Feb 2015 10:21:11 GMT</lastBuildDate><pubDate>Wed, 11 Feb 2015 10:21:11 GMT</pubDate><ttl>60</ttl><item><title>用Dojo实现Ajax请求：XHR、跨域、及其他</title><link>http://www.blogjava.net/jjshcc/archive/2015/02/09/422837.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Mon, 09 Feb 2015 15:09:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2015/02/09/422837.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/422837.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2015/02/09/422837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/422837.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/422837.html</trackback:ping><description><![CDATA[<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">在任何浏览器上方便地实现Ajax请求是每一个Ajax框架的初衷。Dojo在这方面无疑提供了非常丰富的支持。除了XMLHttpRequest之外，动态script、iframe、RPC也应有尽有，并且接口统一，使用方便，大多数情况下都只需要一句话就能达到目的，从而免除重复造轮子的麻烦。而且，Dojo一贯追求的概念完整性也在这里有所体现，换句话说，在使用Dojo的Ajax工具的过程中不会感到任何的不自然，相反更容易有触类旁通的感觉，因为API的模式是统一的，而且这里涉及到的某些概念（如Deferred对象）也贯穿在整个Dojo之中。</p>
<h2>　　Dojo的XHR函数</h2>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　Dojo的XMLHttpRequest函数就叫dojo.xhr，除了把自己取名美元符号之外，这好像是最直接的办法了。它定义在Dojo基本库里，所以不需要额外的require就能使用。它可以实现任何同域内的http请求。不过更常用的是dojo.xhrGet和dojo.xhrPost，它们只不过是对dojo.xhr函数的简单封装；当然根据REST风格，还有dojo.xhrPut和dojo.xhrDelete。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　这些函数的参数都很统一。除了dojo.xhr的第一个参数是http方法名之外，所有的dojo.xhr*系列函数都接受同一种散列式的参数，其中包含请求的细节，例如url、是否同步、要传给服务器的内容（可以是普通对象、表单、或者纯文本）、超时设定、返回结果的类型（非常丰富且可扩展）、以及请求成功和失败时的回调。所有dojo.xhr*函数（实际上是所有IO函数）返回值也都一样，都是一个Deferred对象，顾名思义，它能让一些事情延迟发生，从而让API用起来更灵活。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　下面的两个例子可能会带来一点直观感受：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">dojo.xhrGet({<br style="margin: 0px; padding: 0px; line-height: 10px;" />
url: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">something.html</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
load: function(response, ioArgs){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">用response干一些事</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">        console.log(</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">xhr get success:</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, response)<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> response </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">必须返回response</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    },<br style="margin: 0px; padding: 0px; line-height: 10px;" />
error: function(response, ioArgs){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
console.log(</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">xhr get failed:</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, response)<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> response </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">必须返回response</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    }<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">Deferred对象允许用同步调用的写法写异步调用</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">var deferredResult </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span><span style="margin: 0px; padding: 0px; color: #000000;"> dojo.xhrPost({<br style="margin: 0px; padding: 0px; line-height: 10px;" />
url: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">something.html</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
form: formNode, </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">Dojo会自动将form转成object</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    timeout: </span><span style="margin: 0px; padding: 0px; color: #000000;">3000</span><span style="margin: 0px; padding: 0px; color: #000000;">, </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">Dojo会保证超时设定的有效性</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    handleAs: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">json</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span> <span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">得到的response将被认为是JSON，并自动转为object</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">})<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">当响应结果可用时再调用回调函数</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">deferredResult.then(function(response){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
console.log(</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">xhr get success:</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, response)<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> response </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">必须返回response</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">})</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　首先解释一下timeout。除了IE8之外，目前大多数XMLHttpRequest对象都没有内置的timeout功能，因此必须用 setTimeout。当同时存在大量请求时，需要为每一个请求设置单独的定时器，这在某些浏览器（主要是IE）会造成严重的性能问题。dojo的做法是只用一个单独的setInterval，定时轮询（间隔50ms）所有还未结束的请求的状态，这样就高效地解决了一切远程请求（包括JSONP和 iframe）的超时问题。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　值得一提的还有handleAs参数，通过设置这个参数，可以自动识别服务器的响应内容格式并转换成对象或文本等方便使用的形式。根据文档，它接受如下值：text (默认), json, json-comment-optional, json-comment-filtered, javascript, xml。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　而且它还是可扩展的。其实handleAs只是告诉xhr函数去调用哪个格式转换插件，即dojo.contentHandlers对象里的一个方法。例如 dojo.contentHandlers.json就是处理JSON格式的插件。你可以方便地定制自己所需要的格式转换插件，当然，你也可修改现有插件的行为：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">dojo.contentHandlers.json </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span><span style="margin: 0px; padding: 0px; color: #000000;"> (function(old){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> function(xhr){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
var json </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span><span style="margin: 0px; padding: 0px; color: #000000;"> old(xhr)<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">if</span><span style="margin: 0px; padding: 0px; color: #000000;">(json.someSignalFormServer){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
doSomthing(json)<br style="margin: 0px; padding: 0px; line-height: 10px;" />
delete json.someSignalFormServer<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> json<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})(dojo.contentHandlers.json)</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">一个小技巧，利用传参得到原方法</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　如果要了解每个参数的细节，可以参考<a href="http://docs.dojocampus.org/dojo/xhr" style="margin: 0px; padding: 0px; color: #1a64a2; text-decoration: none;">Dojo的文档</a>。</p>
<h3>　　虚拟的参数类</h3>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　这里特别提一下Dojo在API设计上的两个特点。其一是虚拟的参数类概念：通过利用javascript对象可以灵活扩展的特点，强行规定一个散列参数属于某个类。例如dojo.xhr*系列函数所接受的参数就称为dojo.__XhrArgs。这个类并不存在于实际代码中（不要试图用 instanceof验证它），只停留在概念上，比抽象类还抽象，因此给它加上双下划线前缀（Dojo习惯为抽象类加单下划线前缀）。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　这样做看起来没什么意思，但实际上简化了API，因为它使API之间产生了联系，更容易记忆也就更易于使用。这一点在对这种类做继承时更明显。例如 dojo.__XhrArgs继承自dojo.__IoArgs，这是所有IO函数所必须支持的参数集合，同样继承自dojo.__IoArgs的还有 dojo.io.script.__ioArgs和dojo.io.iframe.__ioArgs，分别用于动态脚本请求和iframe请求。子类只向父类添加少量的属性，这样繁多的参数就具有了树形类结构。原本散列式参数是用精确的参数名代替了固定的参数顺序，在增加灵活性和可扩展性的同时，实际上增加了记忆量（毕竟参数名不能拼错），使得API都不像看起来那么好用，有了参数类的设计就缓解了这个问题。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　这种参数类的做法在Dojo里随处可见，读源码的话就会发现它们都是被正儿八经地以正常代码形式声明在一种特殊注释格式里的，像这样：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #008000;">/*</span><span style="margin: 0px; padding: 0px; color: #008000;">=====<br style="margin: 0px; padding: 0px; line-height: 10px;" />
dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {<br style="margin: 0px; padding: 0px; line-height: 10px;" />
constructor: function(){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
//summary:<br style="margin: 0px; padding: 0px; line-height: 10px;" />
//...<br style="margin: 0px; padding: 0px; line-height: 10px;" />
//handleAs:<br style="margin: 0px; padding: 0px; line-height: 10px;" />
//...<br style="margin: 0px; padding: 0px; line-height: 10px;" />
//......<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})<br style="margin: 0px; padding: 0px; line-height: 10px;" />
=====</span><span style="margin: 0px; padding: 0px; color: #008000;">*/</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　这种格式可以被jsDoc工具自动提取成文档，在文档里这些虚拟出来的类就像真的类一样五脏俱全了。</p>
<h3>　　Deferred对象</h3>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　另一个API设计特点就是Deferred对象的广泛使用。Dojo里的Deferred是基于MochiKit实现稍加改进而成的，而后者则是受到 python的事件驱动网络工具包Twisted里同名概念的启发。概括来说的话，这个对象的作用就是将异步IO中回调函数的声明位置与调用位置分离，这样在一个异步IO最终完成的地方，开发人员可以简单地说货已经到了，想用的可以来拿了，而不用具体地指出到底该调用哪些回调函数。这样做的好处是让异步IO的写法和同步IO一样（对数据的处理总是在取数据函数的外面，而不是里面），从而简化异步编程。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　具体做法是，异步函数总是同步地返回一个代理对象（这就是Deferred对象），可以将它看做你想要的数据的代表，它提供一些方法以添加回调函数，当数据可用时，这些回调函数(可以由很多个)便会按照添加顺序依次执行。如果在取数据过程中出现错误，就会调用所提供的错误处理函数(也可以有很多个)；如果想要取消这个异步请求，也可通过Deferred对象的cancel方法完成。</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">dojo.Deferred的核心方法如下：<br style="margin: 0px; padding: 0px; line-height: 10px;" />
<br style="margin: 0px; padding: 0px; line-height: 10px;" />
then(callback, errback) </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">添加回调函数</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">callback(result) </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">表示异步调用成功完成，触发回调函数</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">errback(error) </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">表示异步调用中产生错误，触发错误处理函数</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">cancel() </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">取消异步调用</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　Dojo还提供了一个when方法，使同步的值和异步的Deferred对象在使用时写法一样。例如：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">某个工具函数的实现</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">var obj </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span><span style="margin: 0px; padding: 0px; color: #000000;"> {<br style="margin: 0px; padding: 0px; line-height: 10px;" />
getItem: function(){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">if</span><span style="margin: 0px; padding: 0px; color: #000000;">(</span><span style="margin: 0px; padding: 0px; color: #0000ff;">this</span><span style="margin: 0px; padding: 0px; color: #000000;">.item){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">this</span><span style="margin: 0px; padding: 0px; color: #000000;">.item </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">这里同步地返回数据</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">        }</span><span style="margin: 0px; padding: 0px; color: #0000ff;">else</span><span style="margin: 0px; padding: 0px; color: #000000;">{<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> dojo.xhrGet({  </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">这里返回的是Deferred对象</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">                url: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">toGetItem.html</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
load: dojo.hitch(</span><span style="margin: 0px; padding: 0px; color: #0000ff;">this</span><span style="margin: 0px; padding: 0px; color: #000000;">, function(response){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">this</span><span style="margin: 0px; padding: 0px; color: #000000;">.item </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span><span style="margin: 0px; padding: 0px; color: #000000;"> response<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> response<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">用户代码</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">dojo.when(obj.getItem(), function(item){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">无论同步异步，使用工具函数getItem的方式都一样</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">})</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　在函数闭包的帮助下，Deferred对象的创建和使用变得更为简单，你可以轻易写出一个创建Deferred对象的函数，以同步的写法做异步的事。例如写一个使用store获取数据的函数：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">var store </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">new</span><span style="margin: 0px; padding: 0px; color: #000000;"> dojo.data.QueryReadStore({...})<br style="margin: 0px; padding: 0px; line-height: 10px;" />
function getData(start, count){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
var d </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">new</span><span style="margin: 0px; padding: 0px; color: #000000;"> dojo.Deferred() </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">初始化一个Deferred对象</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    store.fetch({<br style="margin: 0px; padding: 0px; line-height: 10px;" />
start: start,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
count: count,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
onComplete: function(items){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">直接取用上层闭包里的Deferred对象</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">            d.callback(items) <br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> d </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">把它当做结果返回</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">}</span></div>
</pre>
</div>
<h2>　　用dojo.io.script跨域</h2>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　dojo.xhr* 只是XmlHttpRequest对象的封装，由于同源策略限制，它不能发跨域请求，要跨域还是需要动态创建script标签。Dojo 没有像JQuery一样把所有东西都封装在一起（JQuery的ajax()方法可以跨域，当然用的是JSONP，所以它不敢把自己称为xhr），而是坚持一个API只干一件事情。毕竟在大部分应用中，同域请求比跨域请求多得多，如果一个应用不需要跨域，就没必要加载相关代码。因此与xhr不同，dojo 的跨域请求组件不在基本库，而在核心库，需要require一下才能使用：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">dojo.require(</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">dojo.io.script</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">) </span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　这个包里面基本上只需要用到一个函数：dojo.io.script.get()。它也返回Deferred对象，并接受类型为 dojo.io.script.__ioArgs的散列参数。受益于虚拟参数类，我们不用从头开始学习这个参数，它继承了dojo.__IoArgs，因此和dojo.xhr*系列的参数大同小异。唯一需要注意的是handleAs在这里无效了，代之以jsonp或者checkString。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　前者用于实现JSONP协议，其值由服务器端指定，当script标签加载后就按照JSONP协议执行这个函数，然后Dojo会自动介入，负责把真正的数据传给load函数。需要指出的是在Dojo1.4以前，这个参数叫callbackParamName，冗长但意义明确。毕竟Dojo太早了，它成型的时候（2005）JSONP这个词才刚出现不久。现在callbackParamName还是可用的（为了向后兼容），不过处于deprecated状态。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　下面的例子从flickr获取feed数据：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">dojo.io.script.get({<br style="margin: 0px; padding: 0px; line-height: 10px;" />
url: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">http://www.flickr.com/services/feeds/photos_public.gne</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
jsonp: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">jsoncallback</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">由flickr指定</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    content: {format: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">json</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">},<br style="margin: 0px; padding: 0px; line-height: 10px;" />
load: function(response){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
console.log(response)<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> response<br style="margin: 0px; padding: 0px; line-height: 10px;" />
},<br style="margin: 0px; padding: 0px; line-height: 10px;" />
error: function(response){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
console.log(response)<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">return</span><span style="margin: 0px; padding: 0px; color: #000000;"> response<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　与jsonp不同，checkString参数专门用于跨域获取javascript代码，它其实是那段跨域脚本里的一个有定义的变量的名字，Dojo会用它来判断跨域代码是否加载完毕，配合前面提到的timeout机制就能实现有效的超时处理。</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">dojo.io.script.get({<br style="margin: 0px; padding: 0px; line-height: 10px;" />
url: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">http://......</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">某个提供脚本的URL</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    checkString: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">obj</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
load: function(response){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">脚本加载完毕，可以直接使用其中的对象了，如obj。</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">        Return response<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
})</span></div>
</pre>
</div>
<h2>　　用dojo.io.iframe传数据</h2>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　dojo.io 包里还有一个工具就是iframe，常用于以不刷新页面的方式上传或下载文件。这个很经典的Ajax技巧在Dojo里就是一句 dojo.io.iframe.send({...})。这个函数接受dojo.io.iframe.__ioArgs，相比 dojo.__IoArgs，它只多了一个method参数，用于指定是用GET还是POST（默认）方法发送请求。下面的例子就实现了通过无刷新提交表单来上传文件：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">dojo.io.iframe.send({<br style="margin: 0px; padding: 0px; line-height: 10px;" />
form: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">formNodeId</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">某个form元素包含本地文件路径</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    handleAs: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">html</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">服务器将返回html页面</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    load: onSubmitted, </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">提交成功</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">    error: onSubmitError </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">提交失败</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">})</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　目前send函数的handleAs参数支持html, xml, text, json, 和javascript五种响应格式。除了html和xml之外，使用其他格式有一个比较特别的要求，就是服务端返回的响应必须具有以下格式：&nbsp;</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #800000;">html</span><span style="margin: 0px; padding: 0px; color: #000000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #800000;">head</span><span style="margin: 0px; padding: 0px; color: #0000ff;">/</span><span style="margin: 0px; padding: 0px; color: #800000;">head</span><span style="margin: 0px; padding: 0px; color: #000000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #800000;">body</span><span style="margin: 0px; padding: 0px; color: #000000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #800000;">textarea</span><span style="margin: 0px; padding: 0px; color: #000000;">真正的响应内容</span><span style="margin: 0px; padding: 0px; color: #0000ff;">/</span><span style="margin: 0px; padding: 0px; color: #800000;">textarea</span><span style="margin: 0px; padding: 0px; color: #000000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">/</span><span style="margin: 0px; padding: 0px; color: #800000;">body</span><span style="margin: 0px; padding: 0px; color: #000000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #0000ff;">/</span><span style="margin: 0px; padding: 0px; color: #800000;">html</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　这是因为服务器返回的东西是加载在iframe里的，而只有html页面才能在任何浏览器里保证成功加载（有个DOM在，以后取数据也方便）。加一个textarea则可以尽量忠实于原始文本数据的格式，而不会受到html的影响。</p>
<h2>　　试试RPC(远程过程调用)</h2>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　如果dojo.xhr*函数以及Deferred机制仍然无法避免代码的混乱，那RPC可能就是唯一的选择了。dojo.rpc包提供了基于简单方法描述语言(SMD)的RPC实现。SMD的原理类似于WSDL（Web服务描述语言），不过是基于JSON的，它定义了远程方法的名称、参数等属性，让 Dojo能创建出代理方法以供调用。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　Dojo提供了两种方式实现rpc：XHR和JSONP，分别对应dojo.rpc.JsonService类和dojo.rpc.JsonpService类，用户可以根据是否需要跨域各取所需。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">一个简单的例子：</p>
<div style="margin: 5px 0px 0px; padding: 5px; background-color: #f7f7f7; font-family: 'Courier New'; border-left-color: #cccccc; word-break: break-all; overflow: auto; line-height: 25.200000762939453px; color: #232323;">
<pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 2em; padding: 0px; font-family: 'Courier New'; font-size: 12px; white-space: pre-wrap; word-wrap: break-word;">
<div style="margin: 0px; line-height: 21.600000381469727px;"><span style="margin: 0px; padding: 0px; color: #000000;">var smdObj </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span><span style="margin: 0px; padding: 0px; color: #000000;"> {<br style="margin: 0px; padding: 0px; line-height: 10px;" />
serviceType: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">JSON-RPC</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">,<br style="margin: 0px; padding: 0px; line-height: 10px;" />
serviceURL: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">http://....</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
methods: [<br style="margin: 0px; padding: 0px; line-height: 10px;" />
{name: </span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">myFunc</span><span style="margin: 0px; padding: 0px; color: #000000;">"</span><span style="margin: 0px; padding: 0px; color: #000000;">, parameters: []}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
]<br style="margin: 0px; padding: 0px; line-height: 10px;" />
}<br style="margin: 0px; padding: 0px; line-height: 10px;" />
var rpc </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span> <span style="margin: 0px; padding: 0px; color: #0000ff;">new</span><span style="margin: 0px; padding: 0px; color: #000000;"> dojo.rpc.JsonpService(smdObj) </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">传入SMD</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">var result </span><span style="margin: 0px; padding: 0px; color: #000000;">=</span><span style="margin: 0px; padding: 0px; color: #000000;"> rpc.myFunc() </span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">直接调用远程方法，返回Deferred对象</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">dojo.when(result, function(result){<br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #008000;">//</span><span style="margin: 0px; padding: 0px; color: #008000;">得到结果</span><span style="margin: 0px; padding: 0px; color: #008000;"><br style="margin: 0px; padding: 0px; line-height: 10px;" />
</span><span style="margin: 0px; padding: 0px; color: #000000;">})</span></div>
</pre>
</div>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　SMD还没有一个被广泛认可的官方标准，一直以来都是Dojo社区领导着它的发展，以后这个模块也有可能发生改变，但整个RPC基本的框架会保持稳定。</p>
<h2>　　结语</h2>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　Ajax请求这个主题太大，本文只能挂一漏万地介绍一点dojo在这方面设计和实现的皮毛，包括基本XHR请求、动态script、iframe请求、以及RPC，并特别强调了几个有Dojo特色的设计，如timeout机制、虚拟参数类、Deferred对象等。</p>
<p style="margin-right: 0px; margin-left: 0px; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; color: #232323; line-height: 28px;">　　Dojo由Ajax领域的先驱们写就，相信从它的代码中我们一定能学到更多的东西。</p><img src ="http://www.blogjava.net/jjshcc/aggbug/422837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2015-02-09 23:09 <a href="http://www.blogjava.net/jjshcc/archive/2015/02/09/422837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dojo 的 build 工具简介</title><link>http://www.blogjava.net/jjshcc/archive/2015/01/29/422538.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 29 Jan 2015 07:20:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2015/01/29/422538.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/422538.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2015/01/29/422538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/422538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/422538.html</trackback:ping><description><![CDATA[<h2 id="major2">何时我们需要 Dojo 的 build 工具</h2>
<p>Dojo 作为一个非常实用的 Ajax 实现框架已经被许多 web2.0 开发人员广泛使用，但使用 Dojo 会导致客户端浏览器需要加载大量的 Dojo 文件，导致应用程序性能下降。解决 Dojo 性能问题的方法之一就是对 Dojo 文件进行定制打包和压缩 ( 提高 Dojo 性能的具体方案请参看&#8220;<a href="http://www.ibm.com/developerworks/cn/web/wa-lo-dojo-perf/" cmimpressionsent="1">提高基于 Dojo 的 Web 2.0 应用程序的性能</a>&#8221;。Dojo 本身已经提供了一套对 Dojo 库文件 ( 自己编写的 Javascript 文件只要符合 Dojo 的规范同样可以进行打包 ) 进行 build 的工具，通过定制库文件和压缩文件的方法来减少浏览器加载文件的时间。</p>
<p>Dojo 的主要库文件 (dojo 包 ) 大小在 1M 左右，dijit 包和 dojox 包大小都在 4M-5M，但我们并不总是需要所有的这些库文件，可以根据开发者自身的需要定制一份 Dojo 库，实际使用的库文件大小往往能大大降低；以笔者目前的开发项目为例，经过定制后实际使用的 Dojo 库文件大小只有 300K 左右。</p>
<p>另外 Dojo 的 build 工具也通过压缩 Javascript 文件的手段来降低浏览器加载文件的时间（该过程中需要使用 ShrinkSafe，有关其详细介绍请参看&#8220;<a href="http://dojotoolkit.org/docs/shrinksafe" cmimpressionsent="1">http://dojotoolkit.org/docs/shrinksafe</a>&#8221;），具体的方法如下：</p>
<ol type="1"><li>压缩 Javascript 文件，包括： 
<ol class="ibm-alpha-list" type="a"><li>删除所有的空格和空行</li><li>删除所有的注释</li><li>将定义变量名用更简短的字符代替</li></ol></li><li>将所有打包的的 Javascript 文件的内容合并为一个文件</li></ol>
<p>经过压缩处理，Javascript 文件的大小总体可减少 30%-50%，同时将所有的 Javascript 文件打包成一个文件也减少了浏览器加载时多次开闭文件的负担，从而降低了加载时间。</p>
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" href="http://www.ibm.com/developerworks/cn/web/0912_shenjc_dojobuild/#ibm-pcon" cmimpressionsent="1">&nbsp;</a></p>
<h2 id="major3">准备工作</h2>
<ul class="ibm-bullet-list"><li>到&#8220;<a href="http://download.dojotoolkit.org/" cmimpressionsent="1">dojo 下载网站</a>&#8221;下载 Dojo 源代码，下载后直接解压即可，设 Dojo 的解压目录为 \dojo（<strong>下文中皆用&#8220;\dojo&#8221;指代 Dojo 文件的解压目录</strong>）；</li><li>下载并安装 JDK( 尽量使用 1.5 以上的版本 )，设置 JAVA_HOME 环境变量；</li></ul>
<p>jdk 下载地址：<a href="http://java.sun.com/javase/downloads/index.jsp" cmimpressionsent="1">http://java.sun.com/javase/downloads/index.jsp</a></p>
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" href="http://www.ibm.com/developerworks/cn/web/0912_shenjc_dojobuild/#ibm-pcon" cmimpressionsent="1">&nbsp;</a></p>
<h2 id="major4">使用 Dojo 的 build 工具</h2>
<p>Dojo 提供的 build 工具位于 \dojo\util\buildsrcipts 下，在 windows 下调用该目录内的 build.bat（linux 下使用 build.sh）文件既可执行 build 工作。</p>
<p>下面是在一个在 windows 下调用 build.bat 的例子：</p>
<p>build profile=base action=release releaseName=myDojo optimize=shrinksafe</p>
<p>该命令中包括了几个最常用的参数，其意义如下：</p>
<ul class="ibm-bullet-list"><li>action: 指定本次命令的类型，提供的三个值是：clean, release, help；</li><li>releaseName：本次 release 的名字，默认为 dojo；</li><li>optimize：本次 build 中进行优化的方式，一般使用 shrinksafe 既可；</li><li>profile：指定 build 使用的 profile 文件，profile 文件中提供了 build 相关的配置信息，在 \dojo\util\buildsrcipts\profiles 目录下有很多 *.profile.js 文件，我们自定义的 profile 文件也放在这个目录下，例子中&#8220;profile=base&#8221;表示指定 base.profile.js 作为 build 的参数。</li></ul>
<p>实际上在使用 Dojo 的 build 工具时，关键在于提供的 profile 文件里的内容，在下面的例子中会详细说明 profile 文件的配置方法。</p>
<h3 id="minor4.1">定制 Dojo 文件</h3>
<p>Dojo 库中提供了大量的文件供使用者调用，但有的时候我们并不是需要所有的这些文件，此时我们可以使用 Dojo 的 build 工具定制一份个性化的 Dojo 库文件，首先我们需要编写一个 profile 文件来描述我们的需求：</p>
<h5 id="listing1">清单 1. profile 文件配置示例 1</h5>
<div class="codesection"><pre class="displaycode"> /* example.profile.js */ 
 dependencies = { 
 layers: [    // 可以根据需要制定多个不同的 layer 
 { 
 name: "example.js",   // 打包生成的 js 文件的名
 dependencies: [       // 需要打包的 js 文件列表
"dojo.date", 
"dojox.uuid"       
 ] 
 } 
 ], 
 prefixes: [       // 设置路径
 [ "dijit", "../dijit" ], 
 [ "dojox", "../dojox" ] 
 ] 
 }</pre></div>
<p><strong><em>注意：</em></strong></p>
<ol type="1"><li><em>dojo.js 是默认被打包的，不需要在 dependencies</em><em>中声明</em></li><li><em>在 prefixes 设置路径应该是相对 dojo\dojo\dojo.js 的路径，../dijit 实际上是 dojo\dijit</em></li></ol>
<p>将该文件 (example.profile.js) 放在 \dojo\util\buildsrcipts\profiles 目录下，执行：</p>
<div class="codesection"><pre class="displaycode"> build profile=example action=release releaseName=myDojo optimize=shrinksafe</pre></div>
<p>build 完成后，会在 \dojo 下生成一个 release 文件夹，如下图所示：</p>
<h5 id="fig1">图示 1. build 后释放的文件示意：</h5><img alt="图示 1. build 后释放的文件示意：" src="http://www.ibm.com/developerworks/cn/web/0912_shenjc_dojobuild/image002.jpg" width="301" /> 
<p>因为我们设置了 build 的参数 releaseName=myDojo, 因此 release 下会生成一个 myDojo 文件夹，本次 build 产生的文件都置于该文件夹下。在 \dojo\release\myDojo\dojo\ 目录下，我们可以找到两个文件：example.js 和 example.uncompressed.js，这就是我们需要的打包后的文件，example.uncompressed.js 只是包含了我们指定的所有 dojo 文件，example.js 则在 example.uncompressed.js 基础上又进行了压缩处理。</p>
<h3 id="minor4.2">build 我们自己的 Javascript 文件</h3>
<p>对于我们自己编写的 Javascript 文件，我们同样可是借助 Dojo 提供的 build 工具进行压缩和打包，前提是这些 js 文件需要按照 Dojo 相关的的规范编写。打包我们自己的 Javascript 文件与打包 Dojo 文件并没有太大的差别，假设我们有两个 Javascript 文件如下：</p>
<h5 id="listing2">清单 2. 假设需要打包的 2 个 Javascript 文件</h5>
<div class="codesection"><pre class="displaycode"> /* my.example1 */ 
 dojo.provide("my.example1");  
 dojo.require("my.example2");   // 声明了对 my.example2 的依赖
 /* 
 * this is a js file witch named example1.js 
 */ 

 /* my.example2 */ 
 dojo.provide("my.example2"); 
 /* 
 * this is a js file witch named example2.js 
 */</pre></div>
<p>在 \dojo 下新建一个文件夹&#8220;my&#8221;, 将上面的两个文件放在该文件夹下，profile 文件配置如下：</p>
<h5 id="listing3">清单 3. profile 文件配置示例 2</h5>
<div class="codesection"><pre class="displaycode"> /* example.profile.js */ 
 dependencies = { 
	 layers: [ 
 { 
        name: "example.js",   
 dependencies: [       
"dojo.date", 
"dojox.uuid", 
"my.example1"     // 注意这里我们只声明了 my.example1 
 ]   
    } 
 ], 
	 prefixes: [ 
    [ "dijit", "../dijit" ], 
 [ "dojox", "../dojox" ], 
 [ "my", "../my"]      // 刚才新建的 my 文件夹需要在此声明路径
	 ] 
 }</pre></div>
<p>执行：</p>
<div class="codesection"><pre class="displaycode"> build.bat profile=example action=release releaseName=myDojo optimize=shrinksafe</pre></div>
<p>请注意，在 profile 文件中，只声明了将 my.example1 进行打包，但在 build 生成的 example.js 中我们会发现 my.example2 中的内容也已经被添加进来了。这是因为在 build 过程中，build 程序在分析 js 文件内容时通过识别一些关键字 ( 例如 dojo.require) 来判断当前文件是否依赖其他的文件，并将这些依赖的文件一同进行打包。因此当 build 程序在 my.example1 中读到 dojo.require("my.example2"); 时，判断出该文件需要依赖另一个文件"my.example2"，根据 prefixes 提供的路径 build 程序找到了 my.example2.js 文件，并将该文件的内容添加进来。</p>
<p>按照上面的例子 build 后，我们自己编写的 Javascript 文件会和我们定制 Dojo 的文件合并在一个文件中，我们可能需要独立使用这些自己编写的 Javascript 文件，那么我们修改一下 profile 文件既可：</p>
<h5 id="listing4">清单 4. profile 文件配置示例 3</h5>
<div class="codesection"><pre class="displaycode"> /* example.profile.js */ 
 dependencies = { 
 layers: [ 
 {   // 这个 layer 用来打包我们定制的 dojo 文件
 name: "mydojo.js",   
 dependencies: [       
"dojo.date", 
"dojox.uuid"
 ] 
 }, 
 {  // 这个 layer 用于打包我们自己的 js 文件
 name: "example.js",   
 dependencies: [       
"my.example1"
 ] 
 } 
 ], 
 prefixes: [ 
 [ "dijit", "../dijit" ], 
 [ "dojox", "../dojox" ], 
 [ "my", "../my"] 
 ] 
 }</pre></div>
<p>执行：</p>
<div class="codesection"><pre class="displaycode"> build.bat profile=example action=release releaseName=myDojo optimize=shrinksafe</pre></div>
<p>这样 build 后在 \dojo\release\myDojo\dojo\ 我们会分别得到 mydojo 和 example 两个 layer 的打包文件：</p>
<ul class="ibm-bullet-list"><li>mydojo.js 和 mydojo.uncompressed.js：打包的是我们定制的 Dojo 文件</li><li>example.js 和 example.uncompressed.js：打包了我们自己编写 Javascript 文件，我们可以根据需要独立使用他们</li></ul>
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" href="http://www.ibm.com/developerworks/cn/web/0912_shenjc_dojobuild/#ibm-pcon" cmimpressionsent="1">&nbsp;</a></p>
<h2 id="major5">需要注意的问题</h2>
<ol type="1"><li>在上面我们已经讲到了 build 程序会按照 dojo.require 等关键字将依赖文件添加进来，因此在每个 layer 的 dependencies 中我们不必列出所有我们需要打包的文件，只需要将一些根文件列出既可 ( 如清单 3 所示 )；另外我们也应该确保这些需要打包的文件以及他们所依赖的其他文件所在的路径都在 prefixes 声明注册过，否则 build 程序会因为找不到所需要的文件而失败。</li><li>上面提到在 build 过程中，会调用 shrinksafe 将 js 文件进行压缩，压缩策略包括将定义的变量名用更为简洁的字符串替代，例如我们定义 <code>&#8221;var identifier&#8221;</code>，经过压缩处理可能就变成了 <code>&#8221;var _v01&#8221;</code>，。如果我们的 Javascript 代码中使用了 <code>eval</code>语句，并且 <code>eval</code>的内容里包含了一些我们定义的变量名，就会导致打包后的文件出现错误而无法使用。例如下面的 Javascript 代码：</li></ol>
<div class="codesection"><pre class="displaycode"> var identifier = &#8220;&#8221;; 
 eval(&#8220;alert(identifier)&#8221;);</pre></div>
<p>因为经过压缩后变量名 identifier 被 build 程序以其他的名字替代，因此在执行 eval 方法 , 也就是调用 alert(identifier) 时，会因为无法识别 identifier 而报出 undefined 的错误。</p>
<div class="ibm-alternate-rule">
<hr />
</div>
<p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" href="http://www.ibm.com/developerworks/cn/web/0912_shenjc_dojobuild/#ibm-pcon" cmimpressionsent="1">&nbsp;</a></p>
<h2 id="major6">小结</h2>
<p>本文站在一个初学者的角度简单地介绍了 Dojo 的 build 工具的使用方法（关键在于 profile 文件的配置），通过以上内容读者应该能够使用该工具进行基本的定制和打包处理，有兴趣的读者可以通过提供的参考资料进行进一步的学习。</p><img src ="http://www.blogjava.net/jjshcc/aggbug/422538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2015-01-29 15:20 <a href="http://www.blogjava.net/jjshcc/archive/2015/01/29/422538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dojo 的扩展,自定义组建</title><link>http://www.blogjava.net/jjshcc/archive/2014/12/05/421099.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Fri, 05 Dec 2014 09:06:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2014/12/05/421099.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/421099.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2014/12/05/421099.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/421099.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/421099.html</trackback:ping><description><![CDATA[<h3>Dijit 的类文件</h3><p style="margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; margin-top: -2px !important; font-size: 1.166em !important; background-color: #ffffff;">Dijit 的类也是一个 Dojo 类，所以 Dijit 类的声明和定义也是用 dojo.declare 函数，如清单 10 和清单 13 所示。Dijit 类既然是 Dojo 类，自然也可以继承其它类或被其它类所继承。实际上，一个 Dijit 类区别于其它 Dojo 类最重要的一点是，Dijit 类都直接或间接地继承于类 dijit._Widget，大部分的 Dijit 类通过 mixin 的方式继承类 dijit._Templated，如清单 13 中的 [dijit._Widget,dijit._Templated]。</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">让我们回过头来看看清单 13，清单 13 中，有一个属性叫 templatePath，从名字就可以看出来，这个属性指定了 template 文件的路径。除了指定 template 文件的路径外，也可以直接把 template 变成一个字符串放到类定义文件中，这种情况下，要用到的属性就是 templateString 了。</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">除了 templatePath 和 templateString 以外，还有很多扩展点可以根据实际需要重载，这些扩展点覆盖了 dijit 的整个生命周期，具体列举如下：</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">constructor：</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">constructor 会在设置参数之前被调用，可以在这里进行一些初始化的工作。Constructor 结束后，便会开始设置 Dijit 实例的属性值，即把 dijit 标签中定义的属性值赋给 dijit 实例。</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">postMixInProperties：</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">如果你在你的 dijit 中重载这个函数，它会在 dijit 展现之前，并且在 dom 节点生成之前被调用。如果你需要在 dijit 展现之前，修改实例的属性，可以在这里实现。</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">buildRendering：</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">通常情况下这个函数你不需要去重载，因为 _Templated 为在这里为你做好所有的事情，包括 dom 节点的创建，事情的连接，attach point 的设置。除非你要开发一套完全不一样的模板系统，否则建议你不要重载这个函数。</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">postCreate：</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">这个函数会在 dijit 创建之后，子 dijit 创建之前被调用。</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">startup：</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">当你需要确保所有的子 dijit 都被创建出来了，你可以调用这个函数。</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">destroy：</p><p style="margin: 0px; padding: 6px 0px; border: 0px; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; color: #222222; line-height: 1.5em; font-size: 1.166em !important; background-color: #ffffff;">会在 dijit 被销毁时被调用，你可以在这里进行一些资源回收的工作</p><img src ="http://www.blogjava.net/jjshcc/aggbug/421099.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2014-12-05 17:06 <a href="http://www.blogjava.net/jjshcc/archive/2014/12/05/421099.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入了解 Dojo 的核心接口</title><link>http://www.blogjava.net/jjshcc/archive/2014/09/01/417570.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Mon, 01 Sep 2014 09:20:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2014/09/01/417570.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/417570.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2014/09/01/417570.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/417570.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/417570.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Dojo 的这些接口大大简化了我们的 Web 前端开发的复杂度，使得我们能够在更短的时间内实现功能更为丰富的应用。这篇文章将重点介绍 Dojo 的核心接口所带给 Web 开发工程师们的各种便利以及它的一些使用技巧。Dojo 核心接口简介Dojo 的核心接口主要位于 Dojo 的三大库（&#8220;dojo&#8221;，&#8220;dijit&#8221;和&#8220;dojox&#8221...&nbsp;&nbsp;<a href='http://www.blogjava.net/jjshcc/archive/2014/09/01/417570.html'>阅读全文</a><img src ="http://www.blogjava.net/jjshcc/aggbug/417570.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2014-09-01 17:20 <a href="http://www.blogjava.net/jjshcc/archive/2014/09/01/417570.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dojo define 和declare的区别</title><link>http://www.blogjava.net/jjshcc/archive/2014/09/01/417569.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Mon, 01 Sep 2014 08:48:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2014/09/01/417569.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/417569.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2014/09/01/417569.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/417569.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/417569.html</trackback:ping><description><![CDATA[<h1>Define<br /></h1><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">先看<a target="_blank" href="https://dojotoolkit.org/documentation/tutorials/1.8/modules/" style="color: #336699; text-decoration: none;">define</a>。作用是定义一个模块（module）。这个模块可以被require引用，引用了之后就可以使用define里面的东西。一个模块想当然，里面干什么事情，不一定全部自己实现。就像人要coding，除了脑子，也不能没有电脑、键盘。因此，define的第一个参数就是将要用到的其他模块引进来。第二个参数描述这个模块具体干什么，并且给第一个参数中的模块分别起一个朗朗上口的名字。就像下面这段代码描述的样子。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">util.js</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_javascript"="" style="width: 700.90625px; color: #333333; line-height: 26px;"><div><strong>[javascript]&nbsp;</strong><div style="position: absolute; left: 551px; top: 860px; width: 18px; height: 18px; z-index: 99;"></div></div><ol start="1"><li style="line-height: 18px;">define([&nbsp;"dojo/dom"],&nbsp;function(dom)&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setRed:&nbsp;function(id){&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dom.byId(id).style.color&nbsp;=&nbsp;"red";&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;</li><li style="line-height: 18px;">});&nbsp;&nbsp;</li></ol></div><br style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">这是一个工具模块，其中一个功能就是把网页上id对应的DOM节点变成红色。当我们要使用它的时候，就可以用require了。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">test.jsp</p><div bg_html"="" style="width: 700.90625px; color: #333333; line-height: 26px;"><div><strong>[html]</strong>&nbsp;<u>&nbsp;</u><div style="position: absolute; left: 514px; top: 1227px; width: 18px; height: 18px; z-index: 99;"></div></div><ol start="1"><li style="line-height: 18px;"><span style="color: #993300; font-weight: bold;">&lt;</span><span style="color: #993300; font-weight: bold;">script</span><span style="color: #993300; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;require(&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;"dojo/ready",&nbsp;"test/util"&nbsp;],&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(ready,&nbsp;util)&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ready(function()&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;<span style="color: red;">id</span>&nbsp;=&nbsp;<span style="color: blue;">"selected_text"</span>;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;util.setRed(id);&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</li><li style="line-height: 18px;"><span style="color: #993300; font-weight: bold;">&lt;/</span><span style="color: #993300; font-weight: bold;">script</span><span style="color: #993300; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li></ol></div><br style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><h1>Declare<br /></h1><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">可以看到，上面的模块util作为工具模块，可以在被引用后任意调用其功能。这是无状态的，就好象是一个singleton的对象。但如果我们想定义&#8220;类&#8221;一样的东西，有状态，可以创建多个对象，就需要在define里用<a target="_blank" href="https://dojotoolkit.org/documentation/tutorials/1.8/declare/" style="color: #336699; text-decoration: none;">declare</a>。最典型的例子就是dijit下面的诸多UI小控件。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">举个很简单的例子，我希望基于dijit.Dialog，创建一个有特殊功能的dialog，每次打开后能把上面的一段text标记为红色。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">RedTextDialog.js</p><div bg_javascript"="" style="width: 700.90625px; color: #333333; line-height: 26px;"><div><strong>[javascript]</strong>&nbsp;<a href="http://blog.csdn.net/eengel/article/details/13021687#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/eengel/article/details/13021687#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><a href="https://code.csdn.net/snippets/140024" target="_blank" title="在CODE上查看代码片" style="padding: 1px; display: inline-block; width: 16px; height: 16px; background-position: 0% 0%; background-repeat: no-repeat;"><img src="https://code.csdn.net/assets/CODE_ico.png" width="12" height="12" alt="在CODE上查看代码片" style="border: none; max-width: 100%; position: relative; top: 1px; left: 2px;" /></a><a href="https://code.csdn.net/snippets/140024/fork" target="_blank" title="派生到我的代码片" style="padding: 1px; display: inline-block; width: 16px; height: 16px; background-position: 0% 0%; background-repeat: no-repeat;"><img src="https://code.csdn.net/assets/ico_fork.svg" width="12" height="12" alt="派生到我的代码片" style="border: none; max-width: 100%; position: relative; top: 2px; left: 2px;" /></a><div style="position: absolute; left: 551px; top: 1766px; width: 18px; height: 18px; z-index: 99;"></div></div><ol start="1"><li style="line-height: 18px;">define([&nbsp;"dojo/_base/declare",&nbsp;"dijit/Dialog",&nbsp;"dijit/_WidgetBase",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"dijit/_TemplatedMixin",&nbsp;"test/util"&nbsp;],&nbsp;function(declare,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dialog,&nbsp;_WidgetBase,&nbsp;_TemplatedMixin,&nbsp;util)&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;declare("test.RedTextDialog",&nbsp;[&nbsp;Dialog,&nbsp;_WidgetBase,&nbsp;_TemplatedMixin&nbsp;],&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title:&nbsp;"Dialog&nbsp;with&nbsp;Red&nbsp;Text",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onDownloadEnd&nbsp;:&nbsp;function()&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;id&nbsp;=&nbsp;"selected_text";&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;util.setRed(id);&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</li><li style="line-height: 18px;">});&nbsp;&nbsp;</li></ol></div><br style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">RedTextDialog可以重写dijit.Dialog所有的方法，也可以自创方法、变量，实现自己想要的任意功能。接下来可以用require使用它。</p><div bg_html"="" style="width: 700.90625px; color: #333333; line-height: 26px;"><div><strong>[html]</strong>&nbsp;<div style="position: absolute; left: 514px; top: 2143px; width: 18px; height: 18px; z-index: 99;"></div></div><ol start="1"><li style="line-height: 18px;"><span style="color: #993300; font-weight: bold;">&lt;</span><span style="color: #993300; font-weight: bold;">script</span><span style="color: #993300; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;require(&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;"dojo/ready",&nbsp;"test/RedTextDialog"&nbsp;],&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function(ready,&nbsp;RedTextDialog)&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ready(function()&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;<span style="color: red;">dialog</span>&nbsp;=&nbsp;<span style="color: blue;">new</span>&nbsp;RedTextDialog();&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dialog.show();&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;</li><li style="line-height: 18px;"><span style="color: #993300; font-weight: bold;">&lt;/</span><span style="color: #993300; font-weight: bold;">script</span><span style="color: #993300; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li></ol></div><br style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;" /><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">可以看到，每次使用RedTextDialog时，都可以创建一个新的对象实例，因此可以做到互相之间没有关系。</p><h1>目录结构</h1><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><img src="http://img.blog.csdn.net/20140103092742203?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZWVuZ2Vs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="border: none; max-width: 100%;" /><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">为了在test.jsp中调用上述js文件，需要在test.jsp声明js文件的位置。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_javascript"="" style="width: 700.90625px; color: #333333; line-height: 26px;"><div><strong>[javascript]</strong>&nbsp;<div style="position: absolute; left: 551px; top: 2775px; width: 18px; height: 18px; z-index: 99;"></div></div><ol start="1"><li style="line-height: 18px;">&lt;script&gt;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;dojoConfig&nbsp;=&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isDebug&nbsp;:&nbsp;false,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parseOnLoad&nbsp;:&nbsp;true,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;async&nbsp;:&nbsp;true,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;packages&nbsp;:&nbsp;[&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;:&nbsp;"test",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;location&nbsp;:&nbsp;"../../js/test"&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;</li><li style="line-height: 18px;">&lt;/script&gt;&nbsp;&nbsp;</li></ol></div><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">最后，约定俗成地，一般define类似util的singleton模块，js文件的名字第一个字母小写；而类似RedTextDialog的类模块，第一个字母大写。</p><img src ="http://www.blogjava.net/jjshcc/aggbug/417569.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2014-09-01 16:48 <a href="http://www.blogjava.net/jjshcc/archive/2014/09/01/417569.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>