Skip to main content

dojo学习笔记 (一)

最近几天开始学习dojo 0.9.0, 主要是看它的源码和测试样例, 以下是这几天的研究成果

一、 dojo 概述
我用的是dojo 0.9.0, 下载压缩包解压后有四个文件夹, 依次为:
dijit: 提供了很多ui控件, 被称为widget。
dojo: 提供了很多跨浏览器的实用函数,
dojox: 似乎是提供了一些插件性质的东西, 我只对dojox.flash有点了解
util:里面只有个doh, 功能不明

二、 dojo库的使用
首要的是在html里导入dojo.js文件, dojo加载支持很多参数, 其中我目前用到的有parseOnLoad和isDebug. 设定参数的方法有两种, 一种是在导入dojo.js前通过javascript建立一个对象djConfig,包含要设定的键值对,如djConfig={isDebug:true}; 另一种是在<script>标签里加入djConfig属性,值为JSON语法的键值对, 如<script djConfig="isDebug:true" src="dojo.js"></script>
一开始我对于后一种方法感到很神奇, 起初我以为javascript可以获得自己所在标签的信息, 后来看dojo.js, 查找djConfig, 发现它一上来就判断djConfig是否存在, 否则就建立新值,这时我认为djConfig标签可以作为一个对象在javascript中可以访问, 但亲自尝试后发现并不行。于是我甚至认为这是dojo的一个bug, 但在随后的研究中我发现它确实起作用,于是不得不再认真得看dojo.js(当然是dojo.js.uncompressed.js), 发现原来它会遍历所有script标签,并对导入dojo的标签的djConfig进行处理, 实际上就是加上一对括号然后eval一下。 此时我才恍然大悟。
再说说那两个参数, isDebug不必多说, parseOnLoad是指定dojo.js是否在html加载完毕后进行扫描,识别通过标记方法声明的对象(比如dijit的widget就都支持这种声明, 十分方便)如<div dojoType=dijit.form.Menu> </div>

三、dojo库的几个常用函数
1.dojo.connect(source_obj, event, func)或dojo.connect(source_obj, event, target_obj, target_method)
这个函数相当于把自定义的函数绑在source_obj.event上, 当此事件发生(即这个函数被调用)后,便会调用source_obj.func或target_obj.target_method, 而传进去的参数跟source_obj.event得到的参数相同。
这个函数十分方便, 也是我最早听说的几个dojo实用函数之一, 但关于其实现方法, 我是看了源码才明白。

2.dojo.provide(package_name)
这个是声明当前js提供的包名, 与dojo.require配合使用

3.dojo.require(package_name)
这个指定导入一个包, 这也是十分有用的, 一个是它非常智能, package_name一般为A.B.C的格式,我们暂且称A为bass_name, 它会根据A找到基准目录, 默认是按dojo.js所在路径加上../A,不过也可以用dojo.registerModulePath注册自定义的路径(dojo已内置了一些包的路径, 如dojo, doh)。有了基准路径后, 它会首先尝试B/C.js, 看是否成功, 否则再试B.js,如果有多极, 就逐层往上退。 如果一直找不到就报错。
另一个有用的地方是它可以实现动态导入和避免重复导入, 这一方面非常适合动态的Ajax, 又保证了性能。

4.dojo.declare(class_name, base_class, properties)
dojo提供的一个OOP机制, 而这个是声明一个新类, 举例说明:
dojo.declare("son", father, {
constructor:function(){
alert("hi");
}
});
这样就声明了一个名为son的类, 父类为father, 以后可以用 new son()来创建一个实例
另外base_class可以为null或数组, 后者时,里面必须全为function对象, 以后第一个元素为新类的父类, 其他类只是为了继承其方法。
关于继承, 首先constructor是构造函数, 不会覆盖父类的构造函数, 并且父类的构造函数会被自动调用, 而其他函数则会覆盖父类的。
此外, properties中也可以定义成员变量。

5.dojo.body(), dojo.doc
前者返回body的DOM node, 后者是当前document对象, 一般就是当前的document, 不过由于可以设置整体的上下文, 如dojo.setContext, 所以在dojo框架下应该尽量使用dojo.doc

6.dojo.byId(id_string)
应该比document.getElementById有所增强, 但无论如何, 精致的名字也是诱人之处。

当然还有很多其他函数, 比如dojo.io.bind。 只是我现在还没看到网络通信部分, 等下次再补上吧。

四、dijit库的使用
dijit库的函数我主要是用的dijit.byId, 注意他和dojo.byId的不同, 这里是根据id返回已经生成的dijit的widget对象, 并不是DOM node

dijit提供的控件主要有两种生成方法, 一种是用javascript直接生成, 如new dojo.form.Button(null, node), 另一种是在html中作标记, 如<button dojoType=dijit.form.Button label="button"></button>
关于其生成widget的机制, 我目前所知是它从原始DOM节点中获取信息, 如id, label, dojoType之类, 然后据此生成一个widget, 它本身应该是绑定了一个自己的DOM节点, 最后再将它替换原始DOM节点。

根据dijit.js,在创建一个widget过程中会调用如下几个函数
postMixInProperties: 刚刚从原始节点读入信息后调用, 如果扩展已有widget,可通过connect此函数来为widget对象添加新的属性(每个widget只从原始DOM节点(可用this.srcNodeRef得到其引用)中获取需要的节点, 其他的一概抛弃, 如果需要扩展, 要在销毁前得到它,而这里所列的几个函数中,仅有此函数执行时srcNodeRef尚未背销毁)
buildingRendering:刚刚为当前widget创建好DOM节点时调用
postCreate: 当前widget已创建好并放入UI后调用
startup: 所有widget都创建好后依次为每个widget调用此函数

尽管dijit提供了非常丰富的控件, 但也未必就能满足全部需要。 因此有时需要在现有控件基础上进行扩展。这时上面三个函数就显得非常有用。 不过需要注意的是, 用dojo.declare声明一个子类时, 不能直接重定义上面三个函数,否则父类的方法会被覆盖, 而且dojo似乎没有提供super之类的属性。 我的解决方法是用dojo.declare声明时仅添加新函数,而之后再用dojo.connect对已有函数进行扩展。 如果用此方法, 需要注意, 如果新类叫childClass, 那么应该connect childClass.prototype的方法, 我一开始忘了这一点, 结果怎么都不起作用。

五、其他
dojo与Firebug支持得非常好, 它能自动识别Firebug并与其交互, 再配合Firebug的强大功能, 开发javascript 轻松了很多

六、总结
通过几天的学习, 我对dojo库的基本思想和基本实现方法都有了些了解, 也十分欣赏和钦佩它的结构。它充分利用了javascript的灵活性, 创造了很多异想天开般的设计, 令我大开眼界
就先写这么多, 能些的也就是这么多了。 随着学习的深入, 我会再补充这个学习笔记的。

Comments

Alfred Wang said…
好文章,我最近也在学习dojo,受益了:)
一品凡心 said…
good article, but I still not found the function to substitude dom functions

Popular posts from this blog

Determine Perspective Lines With Off-page Vanishing Point

In perspective drawing, a vanishing point represents a group of parallel lines, in other words, a direction. For any point on the paper, if we want a line towards the same direction (in the 3d space), we simply draw a line through it and the vanishing point. But sometimes the vanishing point is too far away, such that it is outside the paper/canvas. In this example, we have a point P and two perspective lines L1 and L2. The vanishing point VP is naturally the intersection of L1 and L2. The task is to draw a line through P and VP, without having VP on the paper. I am aware of a few traditional solutions: 1. Use extra pieces of paper such that we can extend L1 and L2 until we see VP. 2. Draw everything in a smaller scale, such that we can see both P and VP on the paper. Draw the line and scale everything back. 3. Draw a perspective grid using the Brewer Method. #1 and #2 might be quite practical. #3 may not guarantee a solution, unless we can measure distances/p...

[转] UTF-8 and Unicode FAQ for Unix/Linux

这几天,这个东西把我搞得很头疼 而且这篇文章好像太大了,blogger自己的发布系统不能发 只好用mail了 //原文 http://www.cl.cam.ac.uk/~mgk25/unicode.html UTF-8 and Unicode FAQ for Unix/Linux by Markus Kuhn This text is a very comprehensive one-stop information resource on how you can use Unicode/UTF-8 on POSIX systems (Linux, Unix). You will find here both introductory information for every user, as well as detailed references for the experienced developer. Unicode has started to replace ASCII, ISO 8859 and EUC at all levels. It enables users to handle not only practically any script and language used on this planet, it also supports a comprehensive set of mathematical and technical symbols to simplify scientific information exchange. With the UTF-8 encoding, Unicode can be used in a convenient and backwards compatible way in environments that were designed entirely around ASCII, like Unix. UTF-8 is the way in which Unicode is used under Unix, Linux, and similar systems. It is now time to make sure that you are well familiar ...

Moving Items Along Bezier Curves with CSS Animation (Part 2: Time Warp)

This is a follow-up of my earlier article.  I realized that there is another way of achieving the same effect. This article has lots of nice examples and explanations, the basic idea is to make very simple @keyframe rules, usually just a linear movement, then use timing function to distort the time, such that the motion path becomes the desired curve. I'd like to call it the "time warp" hack. Demo See the Pen Interactive cubic Bezier curve + CSS animation by Lu Wang ( @coolwanglu ) on CodePen . How does it work? Recall that a cubic Bezier curve is defined by this formula : \[B(t) = (1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\ 0 \le t \le 1.\] In the 2D case, \(B(t)\) has two coordinates, \(x(t)\) and \(y(t)\). Define \(x_i\) to the be x coordinate of \(P_i\), then we have: \[x(t) = (1-t)^3x_0+3(1-t)^2tx_1+3(1-t)t^2x_2+t^3x_3,\ 0 \le t \le 1.\] So, for our animated element, we want to make sure that the x coordiante (i.e. the "left" CSS property) is \(...