转自:http://blog.csdn.net/dojotoolkit/article/details/5935844javascript
Dojo 提供了一个很是强大的javascript控件库. 在使用dojo以前,用户基本上不须要具有任何基础知识. 你能够用script远程连接到dojo(dojo.js), 也能够把dojo.js下载到本地并用script标签加载.html
若是你不太了解dojo, 能够参考一下以下资料:java
大致上,dojo.js和jquery.js 或者 prototype js, 里面有不少开发web应用的经常使用的特性: 包括:jquery
不只如此, dojo还有不少其余javascript库(jquery, ext等等)所不具备的功能. 其中一个很重要的功能就是模块化的机制 - 模块系统(dojo.require()
). JavaScript 和 浏览器自己以及其余的javascript库并不支持这种特性, dojo很好的解决了这种问题.web
dojo.require('my.module')
用于加载javascript文件, 功能相似于script标签的做用.跨域
假设你有一个本地的开发环境,目录结构以下:(http://localhost:8888
.)浏览器
index.html
是一个包含 dojo.js 简单页面
.缓存
假设咱们要用Flickr API获取数据, 这时候,咱们就要用到跨域请求, 可是这些功能模块并非在dojo base库里面, 咱们须要另外加载所需的dojo模块:安全
这里咱们能够用script标签解决这种问题, 一样还有另一种方式, 这种方式体现了模块系统的宗旨: 咱们用dojo.require()
加载 dojo.io.script
app
经过
dojo.require()
咱们得到了一个模块系统, 它提供了一系列咱们开发复杂web2.0页面所须要的组件. 接下来的内容咱们会着重介绍模块系统的特性:
首先, dojo.require()会避免重复加载, 若是script脚本被浏览器缓存了, dojo会调用缓存的资源从而避免没必要要的http请求, 事实上,你能够随便调用
dojo.require(), 无论调用了多少
dojo.require(), dojo都会保证一样的模块只会被加载一次.
咱们也能够建立本身的模块. 让咱们回到Flickr API的例子, 咱们要开发一个用Flickr数据的大型web应用, 咱们须要能很好的组织和管理这些javascript代码. 归根结底,咱们须要建立名为flickrApp的命名空间用于保存全部该应用的逻辑功能. 为了达到这个目的, 咱们更新原有的目录结构, 建立一个flickrApp.js文件:
flickrApp.js看起来彷佛仅仅是一个js文件, 但若是你用dojo的眼光来看他, 你会发现他其实应该是一个模块, 为了让dojo识别他是这个模块, 咱们用
dojo.provide()
方法初始化这个js文件,将其变为一个dojo的模块. 咱们加入以下代码到 flickrApp.js 文件中:
dojo.provide()
建立了一个以你传入的字符串(flickrApp
)命名的对象结构(名字空间), 咱们这里是建立了一个名为flickrApp的对象, 该对象建立后, 咱们即可以像定义该对象的各个属性同样来定义该应用(
flickrApp
)
的各个方面, 下面是 flickrApp.js 一个例子:
dojo.require()
来加载咱们自定义的模块到HTML页面上:
问题来了, dojo是怎么知道flickrApp.js模块的文件系统中存放的位置的呢? 答案就是dojo的路径管理机制, dojo会根据你传入
dojo.provide()
的字符串来定位该模块的位置,基准点是dojo.js的上一级目录, 好比dojo.js在
http://localhost:8888/dojo/dojo.js,因此dojo会在
http://localhost:8888/这个目录级别(dojo.js的上一级)来定位全部的模块。 为了说明这个问题, 咱们如今来再一次改变例子的文件结构,使其看起来
更加具备组织性,以下:
此时,全部的应用相关的代码都在flickrApp这个目录(名字空间)下,在这个目录下,咱们能够更进一步将该应用切分红不一样的模块。第一个模块就是data.js模块,包含获取
Flickr数据的逻辑功能,以及跨域,返回数据等等功能。基于这个改变,咱们须要在data.js里面加入
dojo.provide()语句来告诉他新的目录结构的改变,以下(
data.js
):
就像咱们以前所说的,dojo会从dojo.js(http://localhost:8888/dojo/dojo.js
)的上一级目录来开始定位各个模块,因此这里dojo定位咱们的data.js
模块的路径为http://localhost:8888/flickrApp/data.js。此时,咱们的HTML代码也要作相应的改动:
好了,到此为止,咱们来想想,这样作真的有必要吗,咱们为何不能不要借助这种模块系统,而仅仅是把应用程序全部的逻辑功能都放在一个javascript文件中呢? 固然能够。可是dojo实现模块系统的目的在于更好更方便的管理代码,也便于用工具压缩优化代码。
接下来咱们讨论一下最重要的部分:依赖管理.
模块能够包含对其余模块的引用,即在模块中能够require()其余的模块, dojo会帮你管理这些模块,让咱们回到咱们HTML页面:
咱们能够看到,这里咱们会在HTML页面上require 这个dojo.io.script.js模块, 事实上咱们能够把这个
require()语句放到
data.js模块里面,其实这里
data.js模块是依赖于
dojo.io.script.js模块的,dojo会管理这个依赖关系,因此此时
data.js模块以下:
此时,咱们的HTML页面就只须要包含一个 require()
语句 (data.js模块)
.
dojo会管理这些依赖关系,确保data.js依赖于
dojo.io.script.js。
更有甚者,依赖管理还须要一个响应通知,即当全部依赖的模块都被加载完成后的一个响应通知。这件事情能够用dojo.ready()这个函数来实现,
dojo.ready()将会注册一个函数,这个函数会在全部的DOM节点加载完成,而且全部模块及其的依赖模块都加载和解析完成时 被调用。用法以下:
dojo.ready()
能够用在任什么时候间,任何地方,甚至是dojo.ready()的callback方法里面,好比
:
就像前面提到的,当用到dojo的 require()时,dojo会从dojo.js的上一级目录开始查找,好比
require('some.other.module')会从
some/other/module.js开始查找:
其实dojo也提供了咱们定义dojo的默认查找路径的方式,咱们再更新一下咱们应用程序的结构,以下:
能够看到,咱们的模块 - some.other.module.js已经在dojo默认的模块查找路径以外了,咱们要告诉dojo这个结构的变化就要用到
dojo.registerModulePath():
经过dojo.registerModulePath("some", "../../some/")
语句,dojo便知道这个用户自定义的模块的位置,这里,咱们告诉dojo咱们的自定义模块some是在dojo.js的上两级(../../some
),这个时候,dojo便知道了如何去解析这个名字空间(some.other.module
)并加载some.other.module.js文件了。此时此刻,dojo便能识别全部在“
../../some/
”路径下的自定义模块。之因此须要这样作的缘由主要是安全问题,浏览器是不支持javascript访问文件系统的。 若是你对
djConfig 比较了解的话,你会发现其实这个对象也能够用来作“dojo.registerModulePath()
”的工做:
其实dojo关于模块系统的内容还有不少,这里咱们主要是基于本地的dojo,其实dojo还能够以跨域的方式加载(从AOL或者Google CDN),因此模块系统也会去支持这种特性。模块系统的底层实现是基于XHR去请求模块内容的,这些在你用dojo的CDN版本是会改变,这时模块系统会转换到跨域的方式(基于script元素)。
其实这些模块系统的想法也能够在没有dojo的状况下使用。 YUI3.0也有一个相似的实现,一样,也有一些针对模块系统的想法而专门实现的独立的控件库,其中之一就是RequireJS ,他是基于dojo实现的。有兴趣不妨下载下来研究一下。