Dojo是一个用javascript语言实现的开源DHTML工具包(http://dojotoolkit.org/,我这里下载的为dojo-release-1.5.0)。Dojo 提供了一套完整的开发解决方案,包括核心的 JavaScript 库、简单易用的小部件(Widget)等。Dojo框架由四个部分组成:Dojo基本库、Dojo核心库、Dijit(小部件框架和内建的小部件集)和扩展库Dojox。基本库包含最基本的功能,核心库是基本库的扩展,Dijit是用户界面库,而扩展库则是各式各样的扩展组件。Dojo 的最初目标是解决开发 DHTML 应用程序遇到的一些长期存在的历史问题,现在,Dojo 已经成为了开发 RIA 应用程序的利器。
Dojo 是一个分层的体系架构,最上面的一层是 Dojo 的 Widget 系统,Widget 指的是用户界面中的一个元素,比如按钮、进度条和树等,最下面的一层是包系统。Dojo API 的结构与 Java 很类似,它把所有的 API 分成不同的包(package),当您要使用某个 API 时,只需导入这个 API 所在的包。
1.Dojo基础
dojo/目录下包含dojo.js,必须在使用工具包的任何内容之前调用这个脚本元素。dojo.js是模块dojo的模块主脚本。当dojo.js被运行后,全局dojo(一个对象)被创建出来,具有如下功能。
环境属性: 指明运行时环境的一组变量(比如浏览器的版本及其能力)。
语言扩展: 填补JavaScript中漏掉的少数元素
异步编程: 用来进行事件编程和异步回调功能
DOM编程: 使编写DOM更加容易
XHR编程: 通过XHR对象访问服务器
面向对象编程: 用以创建强大而灵活的类层次结构所需要的功能
Dojo加载器: 用以载入JavaScript和Dojo模块的功能
dojo/根目录下面包含的几个dojo中不会自动载入的模块,因此必须显式的通过dojo.require函数载入它们。这些模块包括:
dojo.back 为那些不使用载入URL来导航的应用程序提供返回按钮功能 dojo.behavior 可以附加到节点上的行为 dojo.cldr 一个本地通用数据容器(CLDR Common Data Repository),实现与dojo.i18n协同工作 dojo.colors 方便的CSS颜色操纵功能 dojo.cookie 简单HTTP cookie机制 dojo.currency 解析、格式化及国际化货币数据的功能 dojo.data 泛化数据源的访问功能以及数据源 dojo.date 解析、格式化及国际化时间数据 dojo.dnd 拖放 dojo.fx DOM效果 dojo.i18n 支持多个区域设置,可以与dojo.cldr协同工作 dojo.io 通过脚本或者iframe与服务器进行通信 dojo.number 解析、格式化及国际化数字数据 dojo.parser HTML解析器 dojo.regexp 正则表达式功能 dojo.rpc 远程过程调用(RPC Remote precedure call)框架 dojo.string 字符串功能
2.把dojo和dijit添加到网页
(1).在<head>部分添加标准Dojo首部
<style type="text/css"> @import "/dojoroot/dijit/themes/tundra/tundra.css"; @import "/dojoroot/dojo/resources/dojo.css" </style> <script type="text/javascript" src="/dojoroot/dojo/dojo.js" djConfig="parseOnLoad: true"></script>
@import是用来加载标准的Dojo样式表和Tundra主题的。在Dijit术语里,主题(theme)包含了组件的字体、颜色和大小,让它们看起来更美观。Dijit自带的有三个主题,Tundra、Soria和Nihilo,你也可以开发自己的主题。如果使用Dijit,那么无论使用什么样的主题必须导入dojo.css。当然,如果根本不使用Dijit,也可以不导入它。
声明式小部件(采用非标准的HTML属性): <div dojoType="dijit.layout.ContentPane" href="http://www.yahooo.com"></div> 编程式小部件: var pargrammaticPane = new dijit.layout.ContentPane({href : 'http://www.yahoo.com'});
如果你只使用编程式Dijit组件或者直接使用不带Dijit的简单Dojo,就不需要使用dojo.parser或者djConfig="parseOnLoad:true"。
<script>标签从服务器上导入Dojo代码。使用声明式Dojo元素需要djConfig="parseOnLoad:true"属性。
(2).将<body>标签的class属性值设置为一种Dijit主题 设置与主题对应的body标签的样式类,类名要用小写,并和主题名称一样:tundra、sofia、nihilo。主题只是给Dijit组件使用的,如果你没有使用Dojo中的Dijit,可以不加载它。
(3).根据你需要的组件添加dojo.require语句 Dojo和Dijit组件成为模块,对应于JavaScript文件,你在网页中每引入一个模块就必须写一句dojo.require。例如dojo.require("dijit.layout.ContentPane")就会加载dijit/layout/ContentPane.js。dojo.parser模块是所有使用声明式Dijit组件的页面所必需的。
(4).简单举例
<html> <head> <title>测试第一个DOJO</title> <meta http-equiv="Content-Type" content="text/html;charset=gbk"> <script type="text/javascript" src="dojo.js"></script> <script type="text/javascript"> var init = function() { dojo.query("#id_but").onclick(function(){alert("hello : "+this.value);}); }; dojo.addOnLoad(init); </script> </head> <body> <input type="button" name="na_but" id="id_but" value="click"/> </body> </html>
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gbk"> <title>使用Validition优化页面代码</title> <style type="text/css"> @import "/dojoroot/dijit/themes/tundra/tundra.css"; @import "/dojoroot/dojo/resources/dojo.css" </style> <script type="text/javascript" src="/dojoroot/dojo/dojo.js" djConfig="parseOnLoad: true"></script> <script> dojo.require("dojo.parser"); dojo.require("dijit.layout.ContentPane"); dojo.require("dijit.layout.TabContainer"); dojo.require("dijit.form.ValidationTextBox"); dojo.require("dijit.form.DateTextBox"); </script> <style> .formContainer { width:600px; height:600px; } label { width:150px; float:left; } </style> </head> <body class="tundra"> <div class="formContainer" dojoType="dijit.layout.TabContainer"> <div dojoType="dijit.layout.ContentPane" title="个人信息"> <label for="first_name">姓名:</label> <input type="text" name="first_name" id="first_name" dojoType="dijit.form.ValidationTextBox" trim="true" propercase="true" required="true" size="30" missingMessage="姓名不可空" /> <br/> <label for="email">Email:</label> <input type="text" name="email" id="email" size="30" dojoType="dijit.form.ValidationTextBox" regExp=".*@.*"/> <br/> </div> <div dojoType="dijit.layout.ContentPane" title="地址"> <label for="country">住址:</label> <input type="text" name="country" id="country" size="30" /> <br/> <label for="date_move">搬到此地时间:</label> <input type="text" name="date_move" id="date_move" size="11" dojoType="dijit.form.DateTextBox" /> <br/> </div> </div> </body> </html>
3.djConfig
(1).通过djConfig配置Dojo
Dojo允许开发者重写控制该框架工作的特定全局设置:
当使用dojo.parser去触发dijit对象的自动转换时
应用程序开发的调试阶段
当设置特定的i18n或本地化设置时
如果你重命名了dojo核心组件或在非标准的位置放置了dojo资源
(2).定义djConfig djConfig是dojo内置的一个全局设置对象,Dojo允许开发人员重写djConfig中的设置来控制dojo的运行。我们需要在引用dojo.js前声明djConfig对象,以便在加载dojo.js的时候才能够取得所设置的值,虽然在0.3版本以后dojo支持在加载后设置,但是强烈建议你把声明djConfig的代码作为第一段script。
可以通过三种方式被创建。
<script type="text/javascript" src="dojo.js" djConfig="parseOnLoad: true, isDebug: true,..."></script> 在加载dojo核心(也就是dojo.js)之前明确的创建一个djConfig对象 使用Dojo Toolbox Builder来创建
(a).通过djConfig="..."属性指定djConfig选项 到目前为止,最容易、最常用的方式是在<script>标签中通过djConfig="..."属性来指定djConfig,该标签用来在页面上引入dojo框架(也就是dojo.js)。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Dojo djConfig Tutorial</title> <script type="text/javascript" src="dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script> </head> <body> <p>...</p> </body> </html>
注意:djConfig="..."属性的内容是以逗号分隔的名/值对列表,该名/值对列表和创建JavaScript对象时使用的相同。
(b).加载dojo核心之前明确创建djConfig对象
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Dojo djConfig Tutorial</title> <script type="text/javascript"> var djConfig = { parseOnLoad: true, isDebug: true, locale: 'en-us', extraLocale: ['ja-jp'] }; </script> <script type="text/javascript" src="dojo.js"></script> </head> <body> <p>...</p> </body> </html>
(c).在Dojo Toolbox Builder中引入djConfig
(3).djConfig参数
一个完整的djConfig对象定义如下(值均为dojo的默认值)
vardjConfig={ isDebug:false, debugContainerId:"", bindEncoding:"", allowQueryConfig:false, baseScriptUri:"", parseWidgets:true, searchIds:[], baseRelativePath:"", libraryScriptUri:"", iePreventClobber:false, ieClobberMinimal:true, preventBackButtonFix:true };
(a).调试设置
isDebug: false
当设置为true时,isDebug将通过FireBug或FireBug Lite加载dojo扩展的调试工具。如果设置为真,则所有 dojo.Debug 的输出有效。默认为false
debugContainerId: ""
如果指定,当页面被渲染时,dojo将查找具有指定id的元素,并将FireBug Lite控制台窗口设置在该元素内,该元素作为信息输出容器。如果不指定的话,调试信息将会直接利用 document.write 输出。
debugAtAllCosts: false
提供调试你自己类所需的高级功能
(b).语言和本地化设置
locale: 'en-us'
默认情况下,dojo借助于浏览器导航对象决定应用程序的地区。dojo的地区设置必须在最初时间设置,并且以后不可以再更改。本地标识必须使用小写字母,且不同变体用破折号(-)分开。
extraLocale: ['ja-jp']
除了本地区,开发者可以指定额外的本地化文件,该文件被并行下载。extraLocale变量的参数是代表本地区的字符串数组。extraLocale仅用于处理不常出现事件,比如多语言页面或动态语言切换。extraLocale的一个示例用例是语言教程-页面用使用者的母语是教日语。
(c).在非标准位置查找资源
baseUrl: '/assets/mydojo/'
当在一个给定的站点并行使用多个版本的dojo时,或者核心dojo.js文件为了创建用户构造而被重命名时,baseUrl参数用来指出dojo核心从哪里加载。这对于使用了<base>标签的站点是必要的,该标签使某些浏览器无法识别(比如IE6)。baseUrl的值应当是包含有dojo.js或dojo.xd.js文件的目录。baseUrl的值的定义应当以字符"/"结束。
modulePaths: {'foo': '../../bar'}
使用该参数等效于调用dojo.registerModulePath('foo','../../bar'),对于允许dojo定位定制模块是必须的。
(d).其他选项
afterOnLoad: true
如果你正试图在最初的页面加载之后将dojo.js注入到页面中,就将该值设置为true。
<script type="text/javascript"> var djConfig = { afterOnLoad:true }; window.onload = function(){ var d = document.getElementsByTagName("head")[0].appendChild(document.createElement('script')); d.src = "my/dojo.js"; d.type = "text/javascript"; } </script>
4.在程序中使用djConfig
在dojo.js被加载到页面上之后,传递到djConfig的设置将迁移到dojo.config。
var djConfig = { parseOnLoad:true, myCustomVariable:true } 创建了一个新的名为myCustomVariable的配置参数。通过dojo.config成员在应用程序或widget中使用它。例如一个简单的dojo.declare调用:
dojo.declare("my.Thinger", null, { thingerColor: (dojo.config.myCustomVariable ? "wasTrue" : "wasFalse"), constructor: function(){ if(dojo.config.myCustomVaraible){ ... } } });
通过dojo.config.myCustomVariable来访问djConfig.myCustomVariable。
5.几点说明
<script type="text/javascript" src="dojo.js"></script> <script type="text/javascript"> dojo.require("dojo.NodeList-manipulate"); function testDojoAppend () { var table = dojo.query("#tab"); var begin = new Date().getTime(); for (var j = 0 ; j < 10000 ; j++) { table.append("<tr><td>" + j + "</td><td>TP" +j+ "</td><td>admin</td><td>2011-02-10 15:45:22</td><td>jerry</td><td>Test append " + j + "</td></tr>"); } var end = new Date().getTime(); alert("dom_consume : " + (end - begin)); } </script>
对于在脚本中dojo.require(modulename)将产生如下错误:
Could not load <modulename>; last tried modulename.js
例如在上面的代码中将报错如下:
Could not load 'dojo.NodeList-manipulate': last tried './NodeList-manipulate.js'
当前append方法所需要的NodeLise类无法找到,只需将NodeList-manipulate.js和dojo.js放在相同目录下即可。
建议:dojo是作为一个开发框架而非js库,所以应该将dojo整个开发包放在指定目录下,再通过页面引入。