学习使用 Dojo JavaScript 工具箱开发 HTML 小部件的基础知识。本文为您提供了一个简介,此外,还给出了几个例子为开发过程提供帮助 — 以简单的示例小部件开始,随后是复杂一些的小部件,同时还突出介绍了在开发过程中可能遇到的一些常见问题。
简介
本文的目标是为您提供使用 Dojo JavaScript 工具箱开发 HTML 小部件的基础知识,首先从版本 1.0 开始。本文还描述了几个示例,以简单的小部件开始,之后是较为复杂的小部件,同时还会解决在小部件开发过程中经常遇到的一些常见问题。
何为 Dojo 工具箱?
Dojo 是一种基于 JavaScript 的开源工具箱,可用来开发动态 HTML Web 应用程序。借助它,可以快速构建较标准 HTML 小部件更为复杂的小部件。使用 Dojo 提供的组件可以让 Web 用户界面的可用性、响应性和功能性都有所提高。由 Dojo 提供的低层 API 和兼容性层可帮助您编写跨浏览器兼容的应用程序。
开始之前
在开始之前,需要设置开发环境。为此:
- 从 Dojo 项目站点下载最新版本的 Dojo 工具箱(dojo-release-1.x.x-src.zip 或 dojo-release-1.x.x-src.tar.gz)(相关链接,参见 参考资料)。
- 将此归档文件的内容解压缩到一个文件夹,请注意 dojo.js 文件解压缩到的位置。在 dojo.js 载入页面后,软件包系统将负责管理所有模块的加载。
完成之后,文件夹的结构应该类似图 1。
图 1. dojo 文件展开后的文件夹结构
Dijit 是位于 dojo 之上的一个小部件系统。通过自身的主题 tundra,它为其所有的小部件提供了通用的设计和颜色模式。Dojox 是一个开发包,由 Dojo 工具箱的扩展组成。它可用于开发常见集合中所没有的那些功能。
Dojo 小部件
在浏览网站时,会看到数百个小部件呈现在屏幕前。Web 浏览器的每个按钮都是一个小部件。每个文本输入框也是一个小部件。标准的 HTML 提供了小部件的有限集合:一个输入框、一个按钮和一个超级链接。
Dojo 小部件接受像文本输入框这样的条目并会添加一些函数来获得更具用户友好性的对象,比如一个便于选择日期的图形日历。并且在这个过程中,不会破坏新功能所基于的那个原始条目。
一个 Dojo 小部件封装了一些可视 Web 组件以便于重用。它由三个文件定义:
- 一个 JavaScript 文件,内含小部件逻辑
- 一个可选 HTML 文件,为小部件提供一个类似 HTML 的模板
- 一个 CSS 文件,通常对所有小部件通用(主题),内含包含可应用到小部件 HTML 模板的可视样式
导入 Dojo 工具箱
清单 1 显示了可用来将小部件导入到一个常规 Web 页面的基本 HTML 骨架。
清单 1. 将小部件导入到 Web 页面所需的 HTML 代码
<html> <head> <title>Dojo Toolkit Test Page</title> <style type="text/css"> /* CSS style code */ </style> <script type="text/javascript" src="js/dojo1.2/dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script> <script type="text/javascript"> /* Javascript code */ </script> </head> <body> /* Widgets definition code */ </body> </html> |
第一个脚本标记通过加载 dojo.js bootstrap 文件来初始化 Dojo 工具箱。djConfig 对象的 parseOnLoad 和 isDebug 属性是两个最为常见的配置选项,Dojo 会在运行时对之进行检查。parseOnLoad 在加载时处理标记(mark-up)解析,而 isDebug 启用或禁用调试消息。djConfig 对象还可以在 dojo.js 文件加载前被设置为一个全局变量:
清单 2. 用 djConfig 设置全局变量所需代码
<script type="text/javascript"> var djConfig = { isDebug:true, parseOnLoad:true }; </script> <script type="text/javascript" src="js/dojo1.2/dojo/dojo.js"></script> |
Dojo 包系统
Dojo 是一个包系统,可用来在文件内构造应用程序类并通过 dojo.require 函数加载它们。此函数允许加载在基础 dojo.js 内尚未提供的 Dojo 工具箱的某些部分。
为了创建一个小部件,必须通过添加清单 3 所示的代码行来导入这个小部件声明。
清单 3. 导入小部件声明所需代码
<script type="text/javascript"> dojo.require("widgets.Button"); </script> |
现在,将如下代码插入主体部分:
<body> <div dojoType="widgets.Button">My Button</div> </body> |
dojoType 属性的作用是使 Dojo 工具箱以一种特定的方式管理此标记。在页面加载时,Dojo 解析器会查找在 dojoType 属性内指定的小部件声明,初始化这个小部件并用所获得的小部件 DOM 节点替换此标记。
声明一个小部件
现在,让我们来看看这个 TextBox 小部件示例,定义一个 JavaScript 文件、一个模板文件和一个 CSS 样式文件。
首先,必须创建这个 JavaScript 文件 TextBox.js,内含此小部件的定义和逻辑(参见清单 4)。
清单 4. JavaScript 文件 TextBox.js 的内容
dojo.provide("widgets.TextBox"); dojo.require("dijit._Widget"); dojo.require("dijit._Templated"); dojo.declare( "widgets.TextBox", [dijit._Widget, dijit._Templated], { /** the template path */ templatePath: dojo.moduleUrl("widgets", "templates/TextBox.html"), /** the input DOM node */ inputNode: null, /** the label */ label: "", /** onkeyup handler */ onKeyUp: function() { // give a chance to the browser to update the DOM setTimeout(dojo.hitch(this, this.validate), 0); }, /** validate function */ validate: function() { if ( this.inputNode.value === "Ok" ) { // the text is correct dojo.addClass(this.inputNode, "inputOk"); dojo.removeClass(this.inputNode, "inputError"); } else { // the text is incorrect dojo.removeClass(this.inputNode, "inputOk"); dojo.addClass(this.inputNode, "inputError"); } } } ); |
dojo.provide() 定义新的小部件的名称并注册此类声明。注意到:
- dijit._Widget 和 dijit._Templated 是面向 TextBox 小部件的超类
- templatePath、inputNode 和 label 是小部件的属性
- onKeyUp() 和 validate() 是两个函数,定义了小部件的逻辑
现在,我们可以定义模板文件 TextBox.html,如清单 5 所示。
清单 5. TextBox.html 的内容
<span class="textBox"> ${label}: <input type="text" class="inputOk" dojoAttachPoint="inputNode" dojoAttachEvent="onkeyup: onKeyUp"> </input> </span> |
${label} 将由此小部件实例的 label 属性替代。
dojoAttachPoint 声明会导致 inputNode 小部件的属性被设置为这个输入标记所对应的那个 DOM 节点。