这里将给你对于dojo的启蒙课程。你可能会跟自己说"这段可以跳过了,因为我已经很了解javascript并且对网站开发很了解了。“不过这里有个机会让你认识到其实你的知识并不是那么扎实,还有很多基础的东西需要学习。
当 我们给人们介绍dojo的时候,遇到了两种难题。有些用户已经使用DHTML很久,并且对javascript有了很深的理解,他们清楚 javascript能作什么,不能做什么,在脑海里存在定型思维,有些时候,更难让这些人明白dojo。第二种难题就是对于那些新手,他们太缺乏经验和 对javascript的了解了。
我鼓励这两种朋友都读一下介绍内容,甚至你可以不全看。
什么是Dojo?
其实总结Dojo到底是什么是非常困难的。我说总结Dojo是很困难的,是因为Dojo是一个可扩展的代码集合 (expandable collection of code)。扩展不只是来自于众多开发者,并且你会发现你可以根据你自己的需要扩展自己的一套东西。就是说,你把目光放在Dojo身上的原因是因为 Dojo可以和javascript取长补短。
在开发客户端(client-side development)总共有3个主要部分:events,重复使用DHTML blocks,客户端和服务器传递信息。Dojo在这三方面都很在行,并且使他们变的很容易。
历史
译者注:历史我是真不想翻译了,如果有人很感兴趣的话,可以给我留言,我有时间会翻译的。
。。。。。。。。。。。。
什么是工具(Toolkit)?
很多人认为结构(framework),库(library),工具是同一个意思。但是弄清楚它们之间的区别,对于以后的理解很有帮助。
Framework
在软件开发中,为了让其他的项目可以分享和合作,通常定义一个结构(framework)。一个结构通常包含支持程序(support programs),库和一个脚本程序。你可能认识到Dojo就是framework的一个部分,但并不是framework的本身。
Library
库文件定义了很多可以引用的方法(function),它们是在任何位置都可以运行的,并不是我们平常自己在程序中定义的方法。看了这些,你可能会说“嘿!dojo就是库的集合1。你应该是对的,但是,dojo比一个库的集合要包含得多很多。
Toolkit
看 过前文,你可能还在琢磨到底dojo是作什么的。很明显,他不是一个结构(framework),它是一个工具(toolkit)或者是一个库?最后让我 来解答一下,通常库都是之前定义好的,你可以引用到你的程序中并使用它们,但是在dojo中,我们在这个库外面加了一层封包系统。这样就使它跟一般的库有 些不一样。
在这个系统中,我们把库分成很多部分。有核心方法(core functions),还有很多其他不常用的子库(sub library)。这就使你使用dojo的时候感觉它很简洁。下面会有更具体的分析,会让你更加明白dojo。
Dojo会给你什么
曾经,Netscape盛行一时,大部分人都在使用,所以当时Netscape给出了一个网站制作的标准。好景不长,后来出现了微软的IE,IE当时强过Netscape,成为了新的标准。但是这个标准跟W3C有一定的差别,所以在人们制作网站时,开始向IE新标准靠拢。
很多年过去了,IE依旧不败,而且并没有更新很多。一样多的bug,缺少标准化。慢慢的网虫们开始使用firefox,opera,safari,它们为了跟上W3C的标准,所以更新得很快。
很多同样的功能,但是对于不同的浏览器需要写不同的代码,这对我们来说意味着什么?意味着我们要做出一个完美的网站是很苦难的。这时一个程序员会去做什么呢?
知识补充
如果光使用静态html制作网站,当然不会出现上面的问题,但是这也意味这网站不可能具有交互性,最多的也只是提供一个表单(form)让用户提交,然后再返回一个新的页面显示数据。
Javascript的出现正是为了解决这些难题。
解决所有问题
Dojo不仅是存在于抽象层,并且也是独立存在的。不只是提供一些库,一些方法,一些功能,而且让的代码更加简洁,保证你的代码只包含所需要的部分。
Dojo会让你的生活更加简单,因为他替你链接了很多东西,把你的复杂项目分成一些小问题,让你的代码更简洁,更有效率,并且可以更好的重复使用。
第一章:开始使用Dojo
Dojo有很多版本,你可以一下子不知道该选择哪个,这里可以让你放心,无论你使用的是什么版本,本书中的例子你都可以运行。
下载Dojo
(译者注:这个是我使用的版本,zip文件,你也可以自己到Dojoa主页进行下载。)
Dojo模块(Modules)
Dojo的库定义使用了模块,就像JAVA一样。这样可以让你只引用自己需要的部分,而不是全部,保证了浏览速度。
例如Dojo的event包定义在模块dojo.event中。
(译者注:此部分原著甚是啰嗦,我给精简了一下,有兴趣的朋友可以参见原文。)
引用模块格式:
dojo.require("dojo.module[.sub module]");
例如我们想引用lite effects systems,
dojo.require("dojo.lfx");
这会引入所有lfx下的子模块,当然你也可以使用dojo.lfx.*,如果想单独引用lfx下的toggle模块:
dojo.require("dojo.lfx.toggle");
Widgets
什么是widget呢?一个按钮 ,一个图片,这都是widget,最常见的html widget有链接,按钮,输入框。
使用Dojo可以改变widget ,例如在日期输入框旁边加上一个彩色日历,让用户可以选择日期,与此同时Dojo并不会破坏你原始的输入框,因为Dojo是扩展了你的html而不是替换了它。
使用widget的优势主要三点:
跨平台:使用Dojo widget,无论使用任何浏览器,都会准确的得到正确效果。
自动退化:一些老浏览器可能对javascript支持并不是那么完美,Dojo也可以让它们显示出正确的内容,例如前面彩色日历的例子,如果浏览器不支持,那么Dojo会自动将日历退化到一个简单的选择框,或者其他(根据不同widget而定)。
扩展性:你可以利用Dojo提供的widget创造出新的widget,在这个过程中你并不需要从库中复制任何代码或者修改库中的代码。
如何使用Widget
Widget有很多使用方法。Widget会搜索整个网页框架,然后自动把应该添加的内容加入到当中。
下面是个简单的例子,我们也可以看出WIdget是怎样自动退化的,因为我们并没有给ComboBox定义选择项,而只是一个value,而且所以最后显示出来的只象是一个简单的inputbox,如果用户禁用了javascript,显示结果也会一样。
但是如果我们只想使用W3C标准(译者注:没有那些额外的tag,例如dojoType),我们可以用下面的方法。
你可能注意到了dataUrl,他的作用是把comboBoxData.js中的内容加到comboBox中,但是现在comboBoxData.js中没用任何内容。(译者注:当然你可以随意改变dataUrl的内容,名字不是固定的。)
下面是一个select的例子:
<select dojoType="combobox">
select>
从上面的例子中,你知道了很多事情,但却好像没什么用处,这里只是想告诉你其实dojo并没有那么复杂。
后退和前进
动态网页程序(dynamic web application)避免了频繁的刷新页面,不过通常也带来后退和前进按钮会失去作用。更多的,有的时候,用户可能很难把网页加入收藏夹。
Dojo提供了一个解决办法,让网页程序处理浏览器的后退和前进,并且提供给浏览器一个唯一的地址。这个解决办法就是使用dojo.undo.browser。
使用dojo.undo.browser
在dojo 0.2.2版本中,并没有dojo.undo.browser,这是在0.3以后的版本中才加入的。
首先,需要使用dojo.undo.browser.setInitialStae(state)设定当浏览器第一次载入网页的状态。
理论
动 态网页程序会调用XMLHTTPRequest和DOM来更新网页内容而避免了刷新,更新浏览历史,并且也不会改变浏览器的地址栏。这就意味着当用户点击 了后退按钮,整个网页程序丢失了当前运行的状态(state)。而且即使用户想把当前的网页内容加入收藏夹,也是不可能的,因为收藏夹不会记录网页程序运 行的状态,而只会简单的记录下网页程序的地址(URL)。
开发者可以使用dojo.undo.browser包得到用户点击后退和前进的事件(event),然后根据这些事件来更新页面内容。 dojo.undo.browser通过使用一个隐藏的表单(hidden IFRAME)或者一个唯一的标签(fragment identifier)传递浏览的历史记录。(译者注:可以想像成一个cookie或者一个session,但是这个session信息是存储在hidden IFRAME或者标签中) 例如:
http://some.domain.com/my/path/to/page.html#fragmentIdentifier
(译者注:#fragmentIdentifier就是标签记录)
因为当改变标签的时候并不会使网页刷新,所以非常适合记录当前网页程序的状态。当然开发者可以自定义一个更容易读懂的标签,并且使用户可以把它加入收藏夹。
dojo.undo.browser允许开发者创建一个相对于运行状态的对象(state object),这个对象会得到回叫(callback)当用户点击后退或者前进按钮。
开发
下面是使用dojo.undo.browser之前必须作的一些事情:
1:在djConfig中设置preventBackButtonFix: false。这样保证了隐藏的表单(hidden IFRAME)将会添加到页面当中,如果不加入这段,dojo.undo.browser不会正常工作。
译者注:设置方法就是在header中加入如下代码:
2: 加入dojo.require("dojo.undo.browser");
设定网页程序的初始状态:
dojo.undo.browser.setInitialState(state);
当用户每次点击前进或者后退,state对象都会被调用。
然后我们需要给state对象创建几个方法(function)
得到后退提示:back(),backButtion()或者handle(type),type可以是“back”或者是“forward”。
得到前进提示:forward(),forwardButton()或者handle(type),type如上。
下面是个简单的例子:
var state = {
back: function() { alert("Back was clicked!"); },
forward: function() { alert("Forward was clicked!"); }
};
注册一个state对象使用下面的方法:
dojo.undo.browser.addToHistory(state);
如 果向改变浏览器的地址(URL),引用state对象的changeUrl属性。如果changeUrl是true,dojo.undo.browser 就将产生一个唯一的标签,如果changeUrl被定义为任何其他的值(不包括undefined,null,0和空string),那么这个值就会被使 用为标签。这样用户就可以把当前页加入收藏夹了。
提示
如果你要使用changeUrl,即使你不设定自己的标签,也至少定义为true。
如果你要在本机测试,不要使用IE。因为当IE访问本地文件时不会创建历史列表ifram_history.html。请把网页上传到服务器上测试。
Safari2.0.3+:只有后退按钮可以正常工作,并且只有当changeUrl没用使用的时候。
Opera 8.5.3:不会正常运行。
这里有一个网上的例子:
http://archive.dojotoolkit.org/nightly/tests/undo/test_browser.html
发布Dojo
译者注:此部分的英文版还没有完成,所以暂不翻译了,以后一定会补上。
6月27日更新:
I/O
dojo.io.blind介绍
在我们制作dojo的时候,目的是让用户和开发者都能享受到DHTML程序。在很多朋友的支持下,特别是Aaron Boodman和Mark Anderson,我们已经找到了解决可用性的方法。我们提供了一个单独的易用的API和一个包装类,这个类只需要两个文件。dojo.io包提供了对XMLHTTP和一些其他更复杂的传输结构的支持。
在dojo.io 包中我们一般最常使用的是dojo.io.bind()方法。dojo.io.blind()是一个标准的异步的请求API,它包含了各种传输层 (transport layers),包括queues of iFrames,XMLHTTP,mod_pubsub,LivePage等等。Dojo会试图为当前的请求选择最合适的传输方法,因为在做网站时一般不 会使用到其他传输,所以我们只用到XMLHTTP。dojo接受一个匿名的类,但是在知道这个类的属性的情况下,把它作为方法参数(function argument)。下面的代码是创建一个请求(request),这个请求会从URL返回原始的字符串。
dojo.io.bind({
url: " http://foo.bar.com/sampleData.txt " ,
load: function (type, data, evt){ /* do something w/ the data */ },
mimetype: " text/plain "
});
这就是全部,你提供了一个数据地址,还有一个当你得到返回值时要执行的function。但是如果在请求过程中出错了怎么办呢?我们再来创建一个register来解决:
dojo.io.bind({
url: "http://foo.bar.com/sampleData.txt",
load: function(type, data, evt){ /*do something w/ the data */ },
error: function(type, error){ /*do something w/ the error*/ },
mimetype: "text/plain"
});
同样也可以只创建一个单独的handler来解决:
dojo.io.bind({
url: "http://foo.bar.com/sampleData.txt",
handle: function(type, data, evt){
if(type == "load"){
// do something with the data object
}else if(type == "error"){
// here, "data" is our error object
// respond to the error here
}else{
// other types of events might get passed, handle them here
}
},
mimetype: "text/plain"
});
下面的代码提交一段javascript程序段,然后让服务器运行它,一般我们这么做是为了加速程序运行,注意mimetype:
dojo.io.bind({
url: "http://foo.bar.com/sampleData.js",
load: function(type, evaldObj){ /* do something */ },
mimetype: "text/javascript"
});
如果你想确保程序使用XMLHTTP,可以这样写:
dojo.io.bind({
url: "http://foo.bar.com/sampleData.js",
load: function(type, evaldObj){ /* do something */ },
mimetype: "text/plain", // get plain text, don't eval()
transport: "XMLHTTPTransport"
});
Being a jack-of-all-trades, bind() also supports the submission of forms via a request (with the single caveat that it won't do file upload over XMLHTTP):
作为一个jack-of-all-trades(万事通),bind()同样支持来自于表单提交的数据。
dojo.io.bind({
url: "http://foo.bar.com/processForm.cgi",
load: function(type, evaldObj){ /* do something */ },
formNode: document.getElementById("formToSubmit")
});
以上只是一些最基本的,其实这些可以不用全部由开发者自定义。
RPC
你可以看到,Dojo通过dojo.io.bind提供了简单,强大的方法使用多种多样的I/O functions。但是在开发过程中,程序员会调用很多很多I/O,这同时会给服务器和客户端加重负担。Dojo的RPC服务就是为了减少负担,易用,精简代码而生的。
RPC 的全名是Remote Procedre Calls,或者Remote Method Invocation,(译者:远程method调用)。最基本的,RPC允许开发者调用在远程服务器上的方法(method)。Dojo不仅提供了基本 的RPC client包,而且还扩展了它,使它支持JSON-RPC服务和YAHOO服务。同时你也可以自己写出相对于其他服务的类。
我们假定有一个需要调用服务器端程序的小程序,假设要调用add(x,y)和subtract(x,y)。在没有特殊情况的条件下,我们的客户端会这样写:
add = function(x,y) {
request = {x: x, y: y};
dojo.io.bind({
url: "add.php",
load: onAddResults,
mimetype: "text/plain",
content: request
});
}
subtract = function(x,y) {
request = {x: x, y: y};
dojo.io.bind({
url: "subract",
load: onSubtractResults,
mimetype: "text/plain"
content: request
});
}
你 看,这不是很难。但是无论是我们让服务器运行add和subtract还是让客户端自己计算,这只是一个非常简单的程序。如果我们要调用在服务器上30个 不同method会怎么样呢?我猜我们可能要重复的写几乎一样的代码一遍又一遍,每次都要创建一个请求类(request object),设定URL,设定变量等等。这不仅容易出错,而且还很枯燥。
Dojo的RPC客户端简化了这个过程:
{
"serviceType": "JSON-RPC",
"serviceURL": "rpcProcessor.php",
"methods":[
{
"name": "add",
"parameters":[
{"name": "x"},
{"name": "y"}
]
},
{
"name": "subtract",
"parameters":[
{"name": "x"},
{"name": "y"}
]
}
]
}
以上就是对于服务器的定义。一旦定义创建完毕,其他的事情就简单了,我们还可以创建一个类:
var myObject = new dojo.rpc.JsonService?(defintion);
要使用服务器的方法:
myObject.add(3,5);
我 敢打赌你会在想“我不是只调用方法就够了,我还有得到计算的结果。”你是对的,但这也是非常容易的。服务器端的myObject.add()会返回一个延 缓类(deferred object)。Twisted Python用户可能对延缓类(deferred object)很熟悉,延缓类(deferred object)允许开发者根据返回数据的类型附加一个或更多的回叫(callbacks)和错误处理(errbacks)。这里有一个简单的例子:
var myDeferred = myObject.add(3,5);
myDeferred.addCallback(myCallbackMethod);
我 们把mycallbackmethod作为回叫添加到我们的延缓类mydeferred。这时,8会被传递进mycallbackmethod。另一方 面,我们也可以添加一个errback method来处理服务器返回的出错信息。我们随意添加回叫方法(callback),多少都可以,它们会按照我们定义的顺序被调用。
以上的例子都是围绕dojo.rpc.JsonService展开的。我们还可以使用dojo.rpc.YahooService,规范和结构都是一样的。这两个类都是继承了dojo.rpc.RpcService。要创建自己的类会在第二章中详细介绍。
转载自http://www.blogjava.net/burnet
原文地址 http://www.blogjava.net/burnet/articles/54186.html