虽然各个框架都提供了最常用的Web开发特性,但一直认为Dojo是最强大的,也许没有太绚丽的外观,太完善的文档。但不得否认的是,Dojo中有
太多让人眼前一亮的机制,例如dijit,template,declare。这里的dojo.require也是其中之一,它让你能够很舒服的管理大量
的javascript文件。作为Dojo最基础的机制之一,下面这篇文章可以让你对其有基本的理解,希望能帮助大家更多的了解Dojo!本人在此贴欢迎任何Dojo相关提问^^
========================================================================
Dojo 提供了一个非常强大的javascript控件库. 在使用dojo之前,用户基本上不需要具备任何基础知识. 你可以用script远程链接到dojo(dojo.js), 也可以把dojo.js下载到本地并用script标签加载.
如果你不太了解dojo, 可以参考一下如下资料:
* Dojo 1.4 Cheat Sheet
* Dojo Base Source Tree (1.4.3)
* Dojo Reference Guide
大体上,dojo.js和jquery.js 或者 prototype js, 里面有很多开发web应用的常用的特性: 包括:
* JavaScript Language Helpers
* Object 工具
* Array 工具
* DOM 操作
* 标准的事件机制
* Ajax & 跨域请
* JSON 工具
* 简单特效
* 浏览器兼容
不
仅如此, dojo还有很多其他javascript库(jquery, ext等等)所不具有的功能. 其中一个很重要的功能就是模块化的机制 -
模块系统(dojo.require() ). JavaScript 和 浏览器本身以及其他的javascript库并不支持这种特性,
dojo很好的解决了这种问题.
模块系统
dojo.require('my.module') 用于加载javascript文件, 功能类似于script标签的作用.
假设你有一个本地的开发环境,目录结构如下:(http://localhost:8888 .)
index.html 是一个包含 dojo.js 简单页面 .
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”dojo/dojo.js”></script>
</body>
</html>
假设我们要用Flickr API获取数据, 这时候,我们就要用到跨域请求, 但是这些功能模块并不是在dojo base库里面, 我们需要另外加载所需的dojo模块:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/dojo/dojo.js”></script>
<script src=”/dojo/io/script.js”></script>
</body>
</html>
这里我们可以用script标签解决这种问题, 同样还有另外一种方式, 这种方式体现了模块系统的宗旨: 我们用dojo.require() 加载 dojo.io.script
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/dojo/dojo.js”></script>
<script>
dojo.require(”dojo.io.script”);
//Note: do not include the .js
</script>
</body>
</html>
通过 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 “); //similar to doing flickrApp = {};
dojo.provide() 创建了一个以你传入的字符串(flickrApp )命名的对象结构(名字空间),
我们这里是创建了一个名为flickrApp的对象, 该对象创建后, 我们便可以像定义该对象的各个属性一样来定义该应用( flickrApp )
的各个方面, 下面是 flickrApp.js 一个例子:
dojo.provide(”flickrApp”);
//start creating the application logic for my flickr app
flickrApp.getData = function(){};
现在我们可以用 dojo.require() 来加载我们自定义的模块到HTML页面上:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/dojo/dojo.js”></script>
<script>
dojo.require(”dojo.io.script”);
dojo.require(”flickrApp”);
</script>
</body>
</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 ):
//below is similar to doing var flickrApp = {}; flickrApp.data = {};
dojo.provide(”flickrApp.data “);
// Note: do not include the .js
flickrApp.data.getData = function(){};
就像我们之前所说的,dojo会从dojo.js(http://localhost:8888/dojo/dojo.js
)的上一级目录来开始定位各个模块,所以这里dojo定位我们的data.js
模块的路径为http://localhost:8888/flickrApp/data.js。此时,我们的HTML代码也要做相应的改动:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/dojo/dojo.js”></script>
<script>
dojo.require(”dojo.io.script”);
dojo.require(”flickrApp.data “);
</script>
</body>
</html>
好了,到此为止,我们来想一想,这样做真的有必要吗,我们为什么不能不要借助这种模块系统,而仅仅是把应用程序所有的逻辑功能都放在一个javascript文件中呢? 当然可以。但是dojo实现模块系统的目的在于更好更方便的管理代码,也便于用工具压缩优化代码。
接下来我们讨论一下最重要的部分:依赖管理.
模块可以包含对其他模块的引用,即在模块中可以require()其他的模块, dojo会帮你管理这些模块,让我们回到我们HTML页面:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/dojo/dojo.js”></script>
<script>
dojo.require(”dojo.io.script”);
dojo.require(”flickrApp.data”);
</script>
</body>
</html>
我们可以看到,这里我们会在HTML页面上require 这个dojo.io.script.js模块, 事实上我们可以把这个
require()语句放到 data.js模块里面,其实这里 data.js模块是依赖于
dojo.io.script.js模块的,dojo会管理这个依赖关系,所以此时 data.js模块如下:
dojo.provide(”flickrApp.data”);
dojo.require(”dojo.io.script”);
// Note: dojo.require() should be used after dojo.provide() flickrApp.data.getData = function(){};
此时,我们的HTML页面就只需要包含一个 require() 语句 (data.js模块) .
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/dojo/dojo.js”></script>
<script>
dojo.require(”flickrApp.data”);
</script>
</body>
</html>
dojo会管理这些依赖关系,确保data.js依赖于 dojo.io.script.js。
更有甚
者,依赖管理还需要一个响应通知,即当所有依赖的模块都被加载完成后的一个响应通知。这件事情可以用dojo.ready()这个函数来实现,
dojo.ready()将会注册一个函数,这个函数会在所有的DOM节点加载完成,并且所有模块及其的依赖模块都加载和解析完成时 被调用。用法如下:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/dojo/dojo.js”></script>
<script>
dojo.require(”flickrApp.data”);
dojo.ready(function(){
// Note that dojo.ready() is a shortcut for dojo.addOnLoad() added in Dojo 1.4
// Run code from data.js and all its dependencies safely
});
</script>
</body>
</html>
dojo.ready() 可以用在任何时间,任何地方,甚至是dojo.ready()的callback方法里面,比如 :
dojo.require(”some.module”);
dojo.ready(function(){
//run code from some.module.js and all its dependencies safely dojo.require(’some.other.module’);
dojo.ready(function(){
//run code from some.other.module.js and all its dependencies safely });
});
就像前面提到的,当用到dojo的 require()时,dojo会从dojo.js的上一级目录开始查找,比如 require('some.other.module')会从 some/other/module.js开始查找:
其实dojo也提供了我们定义dojo的默认查找路径的方式,我们再更新一下我们应用程序的结构,如下:
可以看到,我们的模块 - some.other.module.js已经在dojo默认的模块查找路径之外了,我们要告诉dojo这个结构的变化就要用到 dojo.registerModulePath():
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script src=”/js/dojo1.4.1/dojo.js”></script>
<script>
dojo.registerModulePath(”some”, “../../some/”);
dojo.require(”some.other.module”);
</script>
</body>
</html>
通过dojo.registerModulePath("some", "../../some/")
语句,dojo便知道这个用户自定义的模块的位置,这里,我们告诉dojo我们的自定义模块some是在dojo.js的上两级(../../some
),这个时候,dojo便知道了如何去解析这个名字空间(some.other.module
)并加载some.other.module.js文件了。此时此刻,dojo便能识别所有在“ ../../some/
”路径下的自定义模块。之所以需要这样做的原因主要是安全问题,浏览器是不支持javascript访问文件系统的。 如果你对 djConfig
比较了解的话,你会发现其实这个对象也可以用来做“dojo.registerModulePath() ”的工作:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<title>Dojo</title>
</head>
<body>
<script type=”text/javascript”>
var djConfig = {modulePaths:{”some”:”../../some/”}};
</script>
<script src=”/dojo/dojo1.4.1/dojo.js”></script>
<script>
dojo.require(”some.other.module”);
</script>
</body>
</html>
其实dojo关于模块系统的内容还有很多,这里我们主要是基于本地的dojo,其实dojo还可以以跨域的方式加载(从AOL或者
Google
CDN),所以模块系统也会去支持这种特性。模块系统的底层实现是基于XHR去请求模块内容的,这些在你用dojo的CDN版本是会改变,这时模块系统会
转换到跨域的方式(基于script元素)。
Dojo之外
其实这些模块系统的想法也可以在没有dojo的情况下使用。 YUI3.0也有一个类似的实现,同样,也有一些针对模块系统的想法而专门实现的独立的控件库,其中之一就是RequireJS ,他是基于dojo实现的。有兴趣不妨下载下来研究一下。
分享到:
相关推荐
- 模块加载管理:Dojo的动态加载机制可以根据需要按需加载模块,优化页面性能。 - DND(Drag-and-Drop):`dojo.dnd`模块实现了强大的拖放功能,使得交互操作更加直观。 学习Dojo不仅需要理解其模块和包的概念,还...
《dojo中文文档-dojo手册》提供了全面而深入的Dojo框架知识,这是一份非常有价值的资源,对于想要理解和掌握Dojo ...通过阅读和实践,开发者可以深入理解Dojo的精髓,提高开发效率,打造出更加优秀的Web应用。
`dojo.event` 用来绑定和解绑事件,`dojo.event.topic` 提供了消息传递机制,而 `dojo.event.browser` 是浏览器特定事件处理的接口。 `dojo.graphics.color` 模块处理颜色相关的操作,如颜色转换、解析和生成。`...
通过这个文件,你可以深入理解Dojo的各个模块和函数,学习如何在项目中正确地引入和使用Dojo。 【dojo函数.html】可能是讲解Dojo中特定函数或功能的网页,可能涵盖了Dojo的核心函数、类或者方法的用法,例如dojo....
这个“dojo-release-1.0.3-src.zip”压缩包包含了Dojo Toolkit 1.0.3版本的源代码,对于开发者来说,深入理解其内部机制、定制功能或进行二次开发有着极高的价值。 1. **Dojo基础知识** Dojo是一个模块化的...
2. **模块化系统(Dijit和Dojox)**:Dojo引入了`dojo.require`来加载模块,这使得代码组织和重用更为高效。Dijit是Dojo的UI组件库,包含各种可复用的用户界面元素,如按钮、表单控件、布局容器等。Dojox则是扩展库...
4. **dojo.require**: 模块加载机制,引入所需的功能模块。 5. **dojo.on**: 更现代的事件处理函数,替代了dojo.connect,提供了更强大的事件功能。 6. **dojo.ready** / **dojo.addOnLoad**: 确保DOM加载完成后再...
理解这个模块对于理解Dojo的工作原理至关重要。 3. **dojo/_firebug/_firebug**:Dojo 1.1.2版内置了Firebug Lite,这是一个轻量级的开发者工具,即使在没有Firebug的环境中也能提供调试支持。 二、Dojo对象与类 ...
1. **模块化编程**:Dojo Toolkit 使用它的`dojo.require`和`dojo.provide`机制实现了模块化编程,这使得代码组织更加有序,易于维护。开发者可以根据需要引入特定的模块,避免了全局变量污染和不必要的资源加载。 ...
**DOJO 0.4.3 知识点详解** DOJO 是一个强大的JavaScript工具包,专注于提供Web开发所需的各类功能。...尽管现在已经有了更新的版本,但0.4.3版本仍然值得回顾和学习,尤其是对于理解DOJO 框架的基础架构和设计理念。
通过查看这些文件,尤其是`dojo.js`中的注释和调试信息,我们可以更深入地理解Dojo的包加载机制。 5. **调试与优化**: Dojo提供了`dojo/_base/lang`模块来处理语言相关的功能,比如类型检查、函数绑定等。通过...
Dojo的模块和包管理机制允许按需加载,这在优化性能和减小网络传输量方面很有帮助。例如,当你需要使用`dojo.math`模块时,可以通过`dojo.require("dojo.math")`来声明。同样,`dojo.io.*`和`dojo.widget.*`代表了...
这个特性通过 dojo.require() 和 dojo.provide() 函数实现,有助于优化性能和组织代码结构。 3. **Dojo Toolkit**: 这个版本包含了一系列 UI 组件,如按钮、表单控件、面板、树形视图等,这些组件可以方便地集成...
虽然demos可能不直接涉及构建过程,但理解这一系统对于理解Dojo的工作原理和优化技巧至关重要。 10. **模块化开发**:Dojo 0.4.3版本已经强调了模块化开发,通过demos,我们可以看到如何将应用程序拆分成多个模块,...
博主cyhcheng在ITEYE博客上分享了这个项目,这通常是为了教育目的,让其他开发者能够理解DOJO的基础用法。 标签 "源码" 和 "工具" 提供了更多上下文。"源码" 表明我们可以直接访问和分析代码,而"工具" 暗示DOJO是...
在0.3版本中,模块通过`dojo.require`来加载,这种早期的模块化思想对后续的AMD(Asynchronous Module Definition)规范有着深远影响。 4. **事件处理**: Dojo的事件系统允许开发者轻松地绑定和解绑事件,如`dojo....
在文档中,你将学习到如何利用Dojo的模块化系统(`dojo.require`和AMD加载机制)来组织和管理代码,确保项目的可维护性。此外,Dojo的国际化和本地化功能(i18n)也是其亮点,它能帮助开发者轻松创建多语言应用。 ...