赢在执行

这个世界上只有两样东西愈分享愈多,那就是智慧与爱。

BlogJava 首页 新随笔 联系 聚合 管理
  17 Posts :: 11 Stories :: 13 Comments :: 0 Trackbacks

Dojo学习笔记2007年06月05日 星期二 17:18(1. 模块与包)


Intro:

Dojo是一个非常强大的面向对象的JavaScript的工具箱, 建议读者能够去补充一下JavaScript下如何使用OO进行编程的, 这对于你以后阅读Dojo Source有很大的用处

请大家下载dojo 0.3.1, 以下的说明均针对此版本

翻译自http://manual.dojotoolkit.org/WikiHome/DojoDotBook/BookUsingDojo


Getting Started

1: 把Dojo加入到我们的Web程序中

1. 标志

<script type="text/javascript">
djConfig = { isDebug: false };
</script>
djConfig是Dojo里的一个全局对象, 其作用就是为Dojo提供各种选项, isDebug是最常用的属性之一, 设置为True以便能够在页面上直接看到调试输出, 当然其中还有些属性与调试有关, 这里就不罗索了

2. 引用 dojo 的启动代码

<script type="text/javascript" src="/yourpath/dojo.js" />
这样你就引用了dojo的代码, 并可以直接使用其中部分常用的对象, 下载下来的dojo.js是压缩(remove comments and space)后的代码, 要阅读的话,建议阅读dojo.js.uncompressed.js, dojo.js大概有127K, 而未压缩前有211K, ok, 为什么会这么大呢, 原来其已经把部分常用的模块整合进dojo.js里, 因此显得大了一点, build.txt里就说明了默认的dojo.js包含了哪些模块

3. 声明你所要用到的包

<script type="text/javascript">
dojo.require("dojo.math");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.*");
</script>
你就把这些代码当成是java的import语句或C#中的using语句一样, 如果你不require的话, 而模块本身又没有整合在dojo.js中, 是会出现脚本错误的喔

2. 针对不同需求提供的预整合包

Dojo本身是由许多模块所组合而成的, 但是由于用户需求的多样性, dojo针对不同的需求而提供了不同的版本, 用户在下载dojo的时候就看见可以选择很多的版本, 比如Ajax版和Widget版, 每个版本最重要的区别就在于dojo.js文件, 但是除此之外, 每一个版本都是全功能的, dojo.js根据版本的不同而整合进了不同的模块

3. 直接获取Dojo的最新源代码

首先你必须安装 Subversion, 当Subversion在你的电脑上能够正常工作后,你就可以通过如下命令下载dojo的源代码:

svn co http://svn.dojotoolkit.org/dojo/trunk/
这会在你的当前目录下创建一个 trunk 的目录; 如果你希望直接Get到当前目录, 用这个命令:

svn co http://svn.dojotoolkit.org/dojo/trunk/ .
或者你希望Get到当前目录下的 MyDir 目录, 用这个命令:

svn co http://svn.dojotoolkit.org/dojo/trunk/ MyDir

模块与包

模块

Dojo的代码被划分为逻辑单元称之为模块, 这有点类似于Java中的package,除了dojo的模块能够包含类 (类似于java中的classes)和简单函数

比如: 模块"dojo.html"包含了一系列的函数, 比如dojo.html.getContentBox(), 模块"dojo.dnd"包含了一系列的HtmlDragObject的类

注意名称约定, 函数的首字母为小写字母,类的首字母为大写

模块也可以称之为"命名空间"

在多数情况下, dojo的模块只需要定义在一个文件就可以了, 但有时, 一个模块可能划分到多个文件, 比如: 模块dojo.html, 本来是定义在一个文件中, 可是由于功能的增强, 文件逐渐变大, 我们不得不将其拆分为多个文件, 这主要是为性能考虑, 以便浏览器可以只下载其需要用到的代码, 不幸的是其实现细节对于dojo的用户看起来不那么透明, 你必须知道你想要用到的功能到底是包含在哪个文件, 然后才能require并使用它

这样的每一个文件都称之为一个包

dojo.require("dojo.html.extras")
将引用文件 src/html/extras.js, 这将定义模块 dojo.html 的若干(并非所有)函数

据我所知, 尽管单个文件可以定义包里的多个类, 单个脚本文件不能定义多个模块 (在Java可以等效于在一个文件中定义2个类), 并且, 包的名称和模块的名称可以不同, 比如: 包dojo.widget.Button定义了dojo.widget.html.Button

基本上你应该这样认为, 包和模块尽管密切相关, 但是是两个完全不同的实体

为什么会有模块和包这样的概念?

为什么会有模块和包这样的概念? 为了满足你的应用程序只需要加载其所用到的东西的需求, 充分利用模块化设计的优点, dojo维护了最小的足印以便仍能提供你所需要的功能, 为什么要你的用户浪费时间去下载用不到的JavaScript, 当一个包就是一个js文件时, 一个模块本质上就是一个命名空间, 比如: dojo.style 或 dojo.html.extras
多数简单情况下, 一个包包含了一个模块, 但更常见的是, 一个模块可能被拆分为几个包文件

利用包和模块, 将能确保你能够交付最相关的功能代码, 最小程度的减少代码的膨胀和消除由此带来的不好的用户体验,这就是模块设计的主要目标, 通过模块化, 你能够引入自定义模块(你自己拥有的 JavaScript 工具), 并且维护模块对于核心代码库基本不会产生什么影响

另外, Dojo的模块系统也提供了内建的机制来使用代码提供命名空间, 比如, 通过模块dojo.event定义的Dojo的事件系统

怎样引用

设置引用语句

你怎样才能知道该引用哪个包到dojo.require()?

1. 模块

首先, 确定你要使用什么模块, 这个例子我们假定你要使用 dojo.lfx.html

2. 包

搜索代码后你发现dojo.lfx.html定义在2个文件:

src/lfx/html.js
src/lfx/extras.js
根据你要用到的功能, 你可以

dojo.require("dojo.lfx.html");

dojo.require("dojo.lfx.html");
dojo.require("dojo.lfx.extras");

通配符

新用户可能会对dojo.lfx.*这样就可以替代上面2句而感到诧异, 实际上, __package__.js 中已经定义了通配符可以代替的语句, 并且这样可以让dojo根据当时的环境而决定加载具体的模块

Dojo学习笔记(2. djConfig解说)


djConfig是dojo内置的一个全局设置对象,其作用是可以通过其控制dojo的行为

首先我们需要在引用dojo.js前声明djConfig对象,以便在加载dojo.js的时候才能够取得所设置的值,虽然在0.3版本以后dojo支持在加载后设置,但是强烈建议你把声明djConfig的代码作为第一段script

一个完整的djConfig对象定义如下(值均为dojo的默认值)

<script type="text/javascript">
var djConfig = {
isDebug: false,
debugContainerId: "",
bindEncoding: "",
allowQueryConfig: false,
baseScriptUri: "",
parseWidgets: true
searchIds: [],
baseRelativePath: "",
libraryScriptUri: "",
iePreventClobber: false,
ieClobberMinimal: true,
preventBackButtonFix: true,
};
</script>
isDebug是一个很有用的属性,顾名思义,如果设置为真,则所有dojo.Debug的输出有效,开发时应该设置为true,发布时应该设置为false

debugContainerId同样也是与调试有关的,如果不指定的话,调试信息将会直接利用 document.write输出,这样可能会破坏页面的整体布局,所以你可以指定任何一个可以作为容器的html元素的id作为调试信息输出容器

allowQueryConfig,这个属性指明 dojo是否允许从页面url的参数中读取djConfig中的相关属性,当值为true时,dojo会优先从url参数中读取djConfig的其他属性,比如: http://server/dojoDemo.htm?djConfig.debugContainerId=divDebug

baseScriptUri,一般不需要设置,dojo会自动根据你引用dojo.js的路径设置这个值,比如,<script type="text/javascript" src="../dojo/dojo.js"></script>,自动获取的值便是 ../dojo/
ps: 如果你有多个工程需要同时引用dojo.js的话,建议也把dojo当作一个独立的工程,引用的时候采用绝对路径就可以了

parseWidgets,这个是可以控制dojo是否自动解析具有dojoType的html元素为对应的widget,如果你没有使用任何Widget,建议设置为false以加快dojo的加载速度

searchIds,这是一个字符串数组,定义了所有需要解析为widget的html元素的ID,如果ID不在其中的html元素是不会被解析的,当数组为空数组时,则所有具有dojoType的元素都会被解析

还有一个bindEncoding,是用来设置默认的bind请求的编码方式

至于其它的属性,不是用处不大,就是不知道有什么作用

在实际开发中,可以把djConfig的定义放在一个js文件里,并将其作为第一个引用的js文件,这样应该是最方便的。

Dojo学习笔记(3. Dojo的基础对象和方法)

这里所说的基础对象和方法是指的不Require任何包就能够调用的对象和方法

匿名函数

在开始前,我想介绍一下js里的匿名函数,这个在阅读dojo的源代码的时候,会发现到处都有匿名函数

;(function(){
alert(123);
})();
//前面的分号是一个空语句,是可以不要的
匿名函数。一个匿名函数就是一个没有名字的函数。

你可以认为他们是一次性函数。当你只需要用一次某个函数时,他们就特别有用。通过使用匿名函数,没有必要把函数一直放在内存中,所以使用匿名函数更加有效率。

当然你也可以根本不定义函数,但是使用匿名函数可以把你的代码分段,就像C#中的#region一样

dojo.byId

非常有用的一个方法,与prototype.js的著名的$一样

似乎以前的版本还有dojo.byIdArray, 不过最新的版本已经找不到这个函数了(除了src\compat\0.2.2.js)

如果有多个元素具有指定的id,则返回的是一个集合

Usage Example:

dojo.byId("divTest");
dojo.byId("divTest", document);
dojo.byId(document.getElementById("divTest"));


dojo.version

dojo的版本,可以取得major, minor, patch, flag和revision

这个对象没什么太大用处,除非你要根据dojo的版本选择执行你的代码

dojo.raise

抛出一个异常

dojo.errorToString

将异常转换为字符串

Usage Example:

try
{
dojo.raise("打印失败", new Error("文件不存在"));
}
catch(e)
{
alert(dojo.errorToString(e));
}


dojo.render

系统环境对象

dojo.render.name 返回 browser ,说明是工作在浏览器下
dojo.render.ver 返回 4 ,似乎没什么用
dojo.os.win 返回true说明操作系统是Windows
dojo.os.linux 返回true说明操作系统是Linux
dojo.os.osx 返回true说明操作系统是MacOS
dojo.html.ie 返回true说明浏览器是Internet Explorer
dojo.html.opera 返回true说明浏览器是Opera
dojo.html.khtml 返回true说明浏览器是Konqueror
dojo.html.safari 返回true说明浏览器是Safari
dojo.html.moz 返回true说明浏览器是Mozilla FireFox
dojo.svg.capable 返回true说明浏览器支持svg
dojo.vml.capable 返回true说明浏览器支持vml
dojo.swf.capable 返回true说明浏览器支持swf
dojo.swt.capable 返回true说明浏览器支持swt (IBM开发的Standard Widget Toolkit)
如果dojo.html.ie为true的话

dojo.html.ie50 返回true说明浏览器是IE 5.0
dojo.html.ie55 返回true说明浏览器是IE 5.5
dojo.html.ie60 返回true说明浏览器是IE 6.0
dojo.html.ie70 返回true说明浏览器是IE 7.0


dojo.addOnLoad

可以加载指定函数到window.load时执行,好处就是可以很方便的在window.load时执行多个函数

Usage Example:

dojo.addOnLoad(init); //init是一个函数
dojo.addOnLoad(myObject, init); //init是myObject对象的一个方法


dojo.require

如果你想调用一个模块的对象的时候,你应该首先用dojo.require来请求这个模块,dojo会根据你的请求自动取得相应的js文件,并加载到内存中,这样你才能调用或创建其中的对象

dojo会自动维护已加载的模块列表,所以是不会重复加载模块的

Usage Example:

dojo.require("dojo.event");
dojo.requireIf=dojo.requireAfterIf

可以根据指定的条件来决定是否加载指定的模块

Usage Example:

dojo.requireIf(dojo.html.ie, "dojo.html"); //如果dojo.html.ie为true,才会加载dojo.html模块


dojo.provide

除非你要开发自己的模块,不然是用不到这个方法的,你可以这句看成是向系统注册这个模块名称

Usage Example:

dojo.provide("dojo.custom");
dojo.exists

判断指定对象是否具有指定名称的方法

Usage Example:

dojo.exists(dojo, "exists"); //will return true


dojo.hostenv.getText

返回指定url的内容

PS: 由于浏览器的安全限制,因此只能用于取得同域名的url的内容,否则会报告权限不够

Usage Example:

aSync = false; //同步,确保返回内容不为null
silent = true; //不抛出错误
s = dojo.hostenv.getText("http://www.google.com/", aSync, silent); //返回Google的首页的HTML
alert(s);
dojo.debug

输出调试信息,如果在djConfig中指定了debugContainerId,则输出到指定的console容器中,否则直接document.write

所有的调试信息均以 DEBUG: 开头

Usage Example:

dojo.debug("这是调试信息");


dojo.hostenv.println

与dojo.debug类似,不同的是,输出内容没有 DEBUG:

Usage Example:

dojo.hostenv.println("这是一般的输出信息");


dojo.debugShallow

输出指定对象的全部信息(Shallow说明并不会遍历到下一级别的对象属性)以供调试

Usage Example:

dojo.debugShallow(dojo.render.html);
Dojo学习笔记(4. dojo.string & dojo.lang)

模块:dojo.string.common / dojo.stringdojo.string.common 和 dojo.string 是一样的,只要require其中一个就可以使用以下方法dojo.string.trim去掉字符串的空白Usage Example:s = " abc ";dojo.string.trim(s); //will return "abc"dojo.string.trim(s, 0); //will return "abc"dojo.string.trim(s, 1); //will return "abc "dojo.string.trim(s, -1);//will return " abc"
dojo.string.trimStart去掉字符串开头的空白Usage Example:s = " abc ";dojo.string.trimStart(s); //will return "abc "dojo.string.trimEnd去掉字符串结尾的空白Usage Example:s = " abc ";dojo.string.trimEnd(s); //will return " abc"dojo.string.repeat生成由同一字符(串)重复组成的字符串Usage Example:dojo.string.repeat("a", 4); //will return "aaaa"dojo.string.repeat("1234", 3, "-"); //will return "1234-1234-1234"dojo.string.pad使用字符补齐字符串Usage Example:dojo.string.pad("100", 6); //will return "000100"dojo.string.pad("100", 6, "0", 1); //will return "000100"dojo.string.pad("100", 6, "0", -1); //will return "100000"dojo.string.padLeft使用字符补齐字符串开头Usage Example:dojo.string.padLeft("100", 6); //will return "000100"dojo.string.padRight使用字符补齐字符串结尾Usage Example:dojo.string.padRight("100", 6); //will return "100000"
模块:dojo.lang.common / dojo.langdojo.lang.common 和 dojo.lang 是一样的,只要require其中一个就可以使用以下方法
dojo.lang.mixin将一个对象的方法和属性增加到另一个对象上Usage Example:var s1 = {name: "TestObj", test1: function(){alert("this is test1!");}}var s2 = {value: 1000, test2: function(){alert("this is test2!");}}var d = {};dojo.lang.mixin(d, s1, s2); //执行后d就具备了s1和s2的所有属性和方法d.test1();dojo.lang.extend为指定类的原型扩展方法与属性Usage Example:TestClass = function() {};dojo.lang.extend(TestClass, {name: "demo", test: function(){alert("Test!");}});var o = new TestClass(); //TestClass本来是没有test方法的,但是extend以后就有test方法了o.test();dojo.lang.find=dojo.lang.indexOf查找指定对象在指定数组中的位置Usage Example:var arr = [1,2,3,3,2,1];dojo.lang.find(arr, 2); //will return 1dojo.lang.find(arr, 2, true); //will return 1dojo.lang.find(arr, "2", true); //will return -1dojo.lang.find(arr, "2", false); //will return 1dojo.lang.find(arr, 2, true, true); //will return 4dojo.lang.findLast=dojo.lang.lastIndexOf查找指定对象在指定数组中的位置,从后往前查Usage Example:var arr = [1,2,3,3,2,1];dojo.lang.findLast(arr, 2); //will return 4dojo.lang.findLast(arr, 2, true); //will return 4dojo.lang.findLast(arr, "2", true); //will return -1dojo.lang.findLast(arr, "2", false); //will return 4dojo.lang.inArray查找指定对象是否在指定数组中Usage Example:var arr = [1,2,3];dojo.lang.inArray(arr, 1); //will return truedojo.lang.inArray(arr, 4); //will return falsedojo.lang.isObject判断输入的类型是否为对象Usage Example:dojo.lang.isObject(new String()); //will return truedojo.lang.isObject("123")); //will return falsedojo.lang.isArray判断输入的类型是否为数组Usage Example:dojo.lang.isArray({a:1,b:2}); //will return falsedojo.lang.isArray([1,2,3]); //will return truedojo.lang.isFunction判断输入的类型是否为函数Usage Example:dojo.lang.isFunction(function() {}); //will return truedojo.lang.isString判断输入的类型是否为字符串Usage Example:dojo.lang.isString(""); //will return truedojo.lang.isString(0); //will return falsedojo.lang.isAlien判断输入的类型是否为系统函数Usage Example:dojo.lang.isAlien(isNaN); //will return truedojo.lang.isBoolean判断输入的类型是否为布尔类型Usage Example:dojo.lang.isBoolean(2>1); //will return truedojo.lang.isNumber判断输入的类型是否为数值,根据注释所说,此函数使用不太可靠,但是可替换使用的系统函数isNaN也不太可靠dojo.lang.isUndefined判断输入是否为未定义,根据注释所说,此函数有可能会导致抛出异常,推荐使用 typeof foo == "undefined" 来判断
模块:dojo.lang.extrasdojo.lang.setTimeout延迟指定时间后执行指定方法Usage Example:function onTime(msg){dojo.debug(msg)}dojo.lang.setTimeout(onTime, 1000, "test"); //1秒后会输出调试信息"test"dojo.lang.setTimeout(dojo, "debug", 1000, "test"); //1秒后会输出调试信息"test"dojo.lang.getNameInObj获得指定项目在指定对象中的名称Usage Example:dojo.lang.getNameInObj(dojo, dojo.debug); //will return "debug"dojo.lang.shallowCopy返回指定对象的浅表复制副本Usage Example:dojo.lang.shallowCopy({}); //will return a 空对象dojo.lang.firstValued返回第一个存在定义的参数Usage Example:var a;dojo.lang.firstValued(a,2,3); //will return 2以上全部是自己阅读源代码写的总结,如有错误,还请指明。

posted on 2007-10-18 00:31 飛雪(leo) 阅读(426) 评论(0)  编辑  收藏 所属分类: DOJO

只有注册用户登录后才能发表评论。


网站导航: