年前看完了dojo loader的文档,对源代码还没有完全看完,只是看了模块名解析的源代码。 现在直接进入到 Dojo的学习,建立起一个整体的框架。 Hello Dojo! 欢迎来到Dojo! 在这个教程里,你
年前看完了dojo loader的文档,对源代码还没有完全看完,只是看了模块名解析的源代码。 现在直接进入到 Dojo的学习,建立起一个整体的框架。
Hello Dojo!
欢迎来到Dojo! 在这个教程里,你将学习到如何加载Dojo, 并且会开始解释它的核心功能。 你也将会学习至Dojo的基于AMD模式的体系结构。如何给你的网站或者应用通过加载额外的模块来添加额外的功能。 也教会你在错误发生时如何解决。开始
开始使用dojo非常简单, 只需要在网页中包含 dojo.js文件。<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Tutorial: Hello Dojo!</title> </head> <body> <h1 id="greeting">Hello</h1> <!-- load Dojo --> <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.9.2/dojo/dojo.js" data-dojo-config="async: true"></script> </body> </html>
正常的, 一旦你加载完一个javascript库文件后,你将会得到这个库所有的方法, dojo之前是这样的,但在1.7版本后, dojo对源代码采用的是异步模块定义(AMD)格式, 允许整个应用程序的开发完全模块化。 采用AMD的原因是因为它是纯Javascript, 支持浏览器,在应用程序部属时,支持 build工具对资源进行优化。
当dojo.js 被加载完成之后会又有什么是可用的呢? dojo.js 是一个AMD 加载器,它定义了两个全局的函数, require 和 define. 异步模块定义(AMD)你可以查看 AMD介绍教程. 学习完AMD介绍教程后,你会完全理解require是使你可以加载及使用模块,define是用来定义你自己的模块。 一个模块通常是单个的Javascript的源文件。
dojo/dom 和 dojo/dom-construct 是dojo 对html dom 操作的基础模块。 让我们看看,我们如何加载它们及使用它们提供的功能:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Tutorial: Hello Dojo!</title> </head> <body> <h1 id="greeting">Hello</h1> <!-- load Dojo --> <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.9.2/dojo/dojo.js" data-dojo-config="async: true"></script> <script> require([ 'dojo/dom', 'dojo/dom-construct' ], function (dom, domConstruct) { var greetingNode = dom.byId('greeting'); domConstruct.place('<i> Dojo!</i>', greetingNode); }); </script> </body> </html>
require 的第一个参数(行14-17) 是一个你想加载的模块ids数组。 一般, 它们会直接映射到文件名, 如果你下载的了 Dojo的源码版本, 找到dojo文件夹,你可以看到 dom.js 及 dom-construct.js文件。
AMD loader 是异步加载的, 在javascript的异步操作是通过回调函数来实现。 所以在require的第二个参数(行17) 是一个回调函数。 在这个函数里,你可以使用加载到的模块。 AMD loader 将模块作为参数传递给回调函数(保持跟模块Ids数组中相同的排序)。 你可以随便定义回调函数内参数的名称。 但是为了一致性及可读性, 建议使用跟模块Id相同的名称。
在18-19行,你可以看到dom及dom-construct 模块通过DOM 节点的Id来获得一个节点的引用,并组织它们的内容。
* AMD loader 会自动加载请求模块的子依赖(模块定义中define, 第一个数组参数), 所以你只需指定你要依赖的模块,其它的不需要管
定义一个AMD 模块
此时你已经通过一个例子了解模块的加载及使用。 为了定义及加载你自己的模块, 你将需要有一个http 服务器(localhost最好). 在包含有hellodojo.html文件夹个创建一个demo文件夹,在demo文件夹下创建一个myModule.js, 文件结构如下:demo/ myModule.js hellodojo.html
myModule.js 内容如下:
define([ // The dojo/dom module is required by this module, so it goes // in this list of dependencies. 'dojo/dom' ], function(dom){ // Once all modules in the dependency list have loaded, this // function is called to define the demo/myModule module. // // The dojo/dom module is passed as the first argument to this // function; additional modules in the dependency list would be // passed in as subsequent arguments. var oldText = {}; // This returned object becomes the defined value of this module return { setText: function (id, text) { var node = dom.byId(id); oldText[id] = node.innerHTML; node.innerHTML = text; }, restoreText: function (id) { var node = dom.byId(id); node.innerHTML = oldText[id]; delete oldText[id]; } }; });
AMD 的define 函数接受跟require相似的参数 - 模块依赖数组及一个回调函数。 AMD加载器保存回调函数的返回值来作为这个模块的值(返回值代表这个模块)。 所以其它代码通过require 或者define来加载这个模块, 将会获得这个返回值的引用。
CDN 使用
加载本地模块同时从CDN中的dojo需要一些额外的配置(配置Dojo AMD加载器和使用CDN的更多信息可以查看 AMD高级使用和 CDN下模块教程, 如下是更新后的hellodojo.html:<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Tutorial: Hello Dojo!</title> </head> <body> <h1 id="greeting">Hello</h1> <!-- configure Dojo --> <script> // Instead of using data-dojo-config, we're creating a dojoConfig // object *before* we load dojo.js; they're functionally identical, // it's just easier to read this approach with a larger configuration. var dojoConfig = { async: true, // This code registers the correct location of the "demo" // package so we can load Dojo from the CDN whilst still // being able to load local modules packages: [{ name: "demo", location: location.pathname.replace(/\/[^/]*$/, '') + '/demo' }] }; </script> <!-- load Dojo --> <script src="//ajax.googleapis.com/ajax/libs/dojo/1.9.2/dojo/dojo.js"></script> <script> require([ 'demo/myModule' ], function (myModule) { myModule.setText('greeting', 'Hello Dojo!'); setTimeout(function () { myModule.restoreText('greeting'); }, 3000); }); </script> </body> </html>
除了给Dojo添加了配置参数, 我们也重写了主代码, 现在它仅加载demo/myModule, 用它来操作网页中的文本。 像你看到的, 定义和加载一个模块非常简单。 我们已经改变了dojo.js的 url, 省略掉了协议部分(26行), 这样可以依据页面是使用什么协议(http或者https)来创建相对应的URL, 以防在某些浏览器下混合使用双协议的内容产生安全警告。
在AMD模块下组织代码允许你创建可以浏览器下立即执行的模块化的Javascript源代码。并且容易调试。 AMD模块的变量都是使用局部作用域,避免全局命名空间的混乱和最快的找到变量(不用去查找所有作用域链中的变量)。AMD是一个多种实现(dojo loader, requireJs)的标准规范。 所以你可以不受限于其中的一种, AMD模块可以通过任何基于AMD规范的加载器来加载。
等待文档对象模型(DOM)
在开发web应用程序中,常见的一种情况是在执行代码前,你需要确保浏览器已经解析了 DOM. 为了达到这个目的,需要通过特殊的AMD模块来实现,称为 “插件”. 插件的请求像其它模块一样,只是需要在标识符的末尾加个一个"!" 感 叹号。 在任何require及define中的依赖中这个插件,它的callback在 DOM准备好前是不会被触发的。require([ 'dojo/dom', 'dojo/domReady!' ], function (dom) { var greeting = dom.byId('greeting'); greeting.innerHTML += ' from Dojo!'; });
查看DEMO
上面这个例子简单的给greeting元素添加文本 - 需要依赖于DOM已经加载好了(我们不需要在之前的代码使用,因为script元素是在 body后面被包含进来的。 DOM已经被加载了), 再次强调一下, 模块的标识符后面需要一个"!" ; 如果没有, dojo/domReady模块会像其它的模块那样提供简单的功能。
在一些情况下,像dojo/domReady, 我们加载的模块仅需要附代的功能,而不需要引用它。 AMD 加载器没有办法知道这个, 它还是会给回调函数传递依赖数组中每个模块的引用, 所以不需要引用的模块,你只要将它们放到依赖数组的尾部。 然后在回调函数中省略掉不需要的模块就行。
更多的关于DOM操作的功能可以查看 Dojo DOM 函数教程 .
添加视觉效果
现在可以给我们的例子添加一些动画,使它更加有生动。 其中dojo/fx模块我们可以用来给页面添加效果, 让我们通过dojo/fx的 slideTo方法来给greeting添加一个划动的效果。require([ 'dojo/dom', 'dojo/fx', 'dojo/domReady!' ], function (dom, fx) { // The piece we had before... var greeting = dom.byId('greeting'); greeting.innerHTML += ' from Dojo!'; // ...but now, with an animation! fx.slideTo({ node: greeting, top: 100, left: 200 }).play(); });
查看 DEMO
更多的效果及动画可以查看 Dojo Effects 和 Animations
使用Dojo 源代码
我们在教程的例子中使用CDNs, 是因为你可以直接复制代码而不需要改变任何的东西。 虽然它很方便,但也有以下的劣势:- 从性能上来说, 它们是"build" 后的版本, 意思是每一个模块已经是最小化和调优过的。当你出现问题是,很难调试代码。
- 需要你可以访问互联网,而许多情况下是不实际的。
- 在包含你自己的定义的模块时,需要付出更多的努力(更多的执行步骤)
- 如果你需要投放你的应用程序,你需要自己通过build工具来优化性能或者针对特定的浏览器, 你就不能通过CDN build来优化了。
按照以下的步骤开始获得和使用dojo源码:
- 下载Dojo - 在靠近页面的底部下载源代码版本。
- 解压文件到你的项目文件夹,结构如下:
demo/ myModule.js dojo/ dijit/ dojox/ util/ hellodojo.html3. 加载本地的dojo.js, 而不是 CDN:
<script src="dojo/dojo.js"></script>
4. 更新你的包配置
var dojoConfig = { async: true, baseUrl: '.', packages: [ 'dojo', 'dijit', 'dojox', 'demo' ] };
获得帮助
当你遇到困惑或棘手的问题时,你并不孤单。 你可以通过 dojo-interest mailing list中的email地址或者 在线聊天 联系志愿者. 如果你发现了我们文档中的错误 或者有误解及困惑的地方, 可以通过所有文档最下方的返馈链接给我们返馈相关问题。如果你有紧急或者保密的帮助,或者志愿者不能解决的问题时,可以通过 SitePen 来获得商业的支持.
下一步是什么?
入门的Dojo 非常简单,只是添加一个script 标签,及加载需要的模块。 但这只是dojo的皮毛。 依据你的需求, 以下有几种不同的学习路径:- 如果你之前使用过Dojo, 只是想要理解AMD,可以查看 Modern Dojo 教程
- 如果你想给现有的静态网页添加功能及效果,你可以学习 Using dojo/query , Events with Dojo , 以及 effects 和 animations 等教程
- 如果你需要在你的网站上使用Ajax, 请查看 Ajax with Dojo
- 如果你在你的网站或者应用程序中使用丰富的窗口部件, 可以查看 Creating Template-base Widgets教程 以及加上我们的 Dijit widgets教程系列
- 如果你试图了解架构复杂的web应用程序, 并且利用Dojo的实用函数, 请查看 Core Concepts 章节
- 如果你的目标是移动应用程序, 请查 Getting Started with dojox/mobile.