在本小节,您将学习一些很有用的 Dojo 功能,使之更易于使用 DOM 和阵列。要实验本节中的示例,继续使用上小节您在 Firefox 中创建的页面,输入 Firebug 控制台窗口中的代码。
DOM 实用函数通过提供根据 ID 寻找条目的能力或者使用 CSS3 选择器,使得使用 DOM 中的元素比较容易。还有一些其他功能,可以创建和销毁元素,以及操作现有元素内容。
>>> dojo.byId("message").innerHTML;
"This is a DIV element with id attribute message1."
dojo.query("#list li").forEach(function(item) {
console.log(item.innerHTML);
});
>>> dojo.query("#list li").forEach(function(item) { console.log
(item.innerHTML); });
This is the first item in a list
This is the second item in a list
This is the third item in a list
[li,li.highlight,li]
dojo.query(".highlight").style({
backgroundColor: "yellow",color: "red"
});
数组允许您存储一个值集合,在标准 JavaScript 中提供。在 Dojo 中,数组被扩展来包括几个帮助函数。这些扩展的数组被称为 NodeLists。一个 NodeList 可以使用任何标准数组函数,以及其他 Dojo 特定函数,当您使用上一小节中描述的dojo.query
函数时,返回值是一个 NodeList(准确地说是dojo.NodeList
)对象。我们来看看 NodeLists 中可用的函数。
var list = ['My','name','is','Joe'];
dojo.forEach(list,function(item,i) {
console.log((i+1)+'. '+item);
});
>>> var list = ['My','Joe']; dojo.forEac...item,i)
{ console.log((i+1)+'. '+item); });
1. My
2. name
3. is
4. Joe
dojo.indexOf
dojo.indexOf函数使得您可以在一个数组中找出具体一个值的位置。最好是结合示例说明。使用上一小节创建的列表数组,尝试找出值为name
的数组的地址:dojo.indexOf(list,"name");
.
返回结果如清单 11 所示。
清单 11. 结果
>>> dojo.indexOf(list,"name");
1
在数组中值为name
的项下标为 1。记住 JavaScript 数组的下标是从 0 开始的,因此该值是数组的第 2 项。如果您想要尝试使用该函数寻找一个数组中并不存在的值,返回值为-1
。
该函数返回给定值的第一个位置的下标,因此,如果数组中有多个项有相同的值,它只停在第一项上,Dojo 提供一个类似的函数,dojo.lastIndexOf
,允许您寻找特定值的最后一个位置。该函数与dojo.indexOf
运行方式完全一样。
dojo.filter
dojo.filter函数支持您创建一个新数组,这个新数组是另一个数组的过滤版。例如,如果您想为您早期创建的列表数组创建一个新版本,但是又不想包括值为is
的那些项。您可以使用清单 12 所示的代码。
清单 12. 过滤一个数组来创建一个新数组
var filteredList = dojo.filter(list,function(item) {
return item != "is";
});
dojo.forEach(filteredList,"console.log(item)");
This results in the following output:
>>> var filteredList = dojo.filter(list,function(it...dojo.forEach(filteredList,"console.log(item)");
My
name
Joe
其他 NodeList 函数
Dojo 还有一些其他 NodeList 函数,在处理数组时非常有用。dojo.map
函数允许您创建一个新数组 — 现有数组的修改版。例如,如果您想创建一个代表货币值的数字数组。您可以使用一个映射函数以货币格式返回这些值的一个数组。dojo.some
允许您检查在数组中匹配指定标准的项是否至少有一个。类似地,dojo.every
用于检查是否每一项匹配指定标准。NodeList 函数的完整列表及其相关文档,见回页首
Dojo 中的事件处理
多数 JavaScript 库都有一个本地 JavaScript 事件处理的跨浏览器实现,允许您附加函数,在事件触发时调用。这可能很有用,Dojo 通过允许您将函数链接到其他函数进一步延伸了这一概念,这可能是 DOM 事件、对象时间、用户定义函数、或者是 “topics”,我们将在下一节进行讨论。
DOM 事件处理
将函数附加到 DOM 对象的第一个方法是使用dojo.connect
函数。结合示例来说明最好不过。在 Firebug 控制台输入清单 13 中的代码。
清单 13. 使用dojo.connect
附加函数到 DOM 事件
var message = dojo.byId("message");
dojo.connect(message,"onclick",function() {
alert(message.innerHTML);
});
控制台中的输出如清单 14 所示。
清单 14. 输出
>>> var message = dojo.byId("message"); dojo.connect...,function()
{ alert(message.innerHTML); });
[div#message,function(),1]
这真的很棒,但是您不是就希望该功能可以真正地完成一些任务吗?它确实可以。Dojo 已将一个函数附加到 ID 为 “message” 的元素的click
事件处理程序上了。想试试看吗?单击屏幕上的消息 “This is a DIV element with id attribute message.”。 您将看见一个 JavaScript 提示框,如图 4 所示。
图 4. 附加函数到 DOM 事件
漂亮且容易,不是吗?如果您想附加一个事件到数组的所有条目上该怎么办?例如,假设您想要页面上无序列表中的每一项在您单击时都以粗体突出显示。使用清单 15 中的代码就可以很轻松地完成。
清单 15. 附加事件到数组元素上
dojo.query("#list li").forEach(function(item) {
dojo.connect(item,function() {
dojo.style(item,{
fontWeight: "bold"
});
});
});
试试看,是有效的。Dojo 支持您以一种更简洁的方式编写这段代码。不需要使用forEach
对整个数组进行迭代,使用NodeList.connect
快捷函数即可完成,如清单 16 所示。
清单 16. 附加事件到数组元素上(改进的)
dojo.query("#list li").onclick(function(e) {
dojo.style(e.target,{
fontWeight: "bold"
});
});
由于您已经附加了一个事件到这个列表上,在尝试清单 16 中的代码之前刷新页面,确保正常运行。e
参数是Event
对象的一个引用,对象的target
属性帮助您确定触发事件的元素。您可以使用这个来指出粗体样式应该被应用的元素。试一下单击这 3 个列表项,单击之后每一个都会变成粗体。
连接函数到其他函数
在前面的示例中,您可以连接函数到 DOM 事件上。Dojo 也支持您以同样的方式将函数连接到其他函数。这方面的一个示例可能是这样一个函数,在您的页面的某个地方显示一个旋转轮子。当用户执行一个 Ajax 函数时,您想要显示这个图像。类似地,当函数返回一个响应时,您想要隐藏该图像。如果不使用dojo.connect
,您的代码看起来像清单 17 这样。
清单 17. 不使用dojo.connect
将函数连接到其他函数
function toggleImage() {
//Code to show/hide loading image goes here
}
function callAjax() {
toggleImage();
//Code to call Ajax function goes here
}
function handleResponse() {
//Code to handle Ajax response goes here
toggleImage();
}
这段代码没什么问题,toggleImage
函数定义包含在callAjax
和handleResponse
函数中。如果您想添加另一个函数调用,您需要再次修改这些函数来包含额外调用。现在不需要向这些函数本身添加函数调用,只需要使用dojo.connect
来在它们之间建立一个链接。清单 18 显示dojo.connect
方法。
清单 18. 使用dojo.connect
连接函数到其他函数
function toggleImage() {
//Code to show/hide loading image goes here
}
function callAjax() {
//Code to call Ajax function goes here
}
function handleResponse() {
//Code to handle Ajax response goes here
}
dojo.connect(callAjax,toggleImage);
dojo.connect(handleResponse,toggleImage);
这种编码风格未必每个开发人员都会喜欢,但是它允许您以这样一种方式组织您的代码,使它阅读起来更容易些。
发布和订阅主题
Dojo 事件处理最后值得注意的一点是发布和订阅主题的能力。这使得 Dojo 组件可以彼此交互,即使它们没有意识到彼此的存在。例如,假设您定义了一个名为printName
的主题,它绑定了一个message
对象包含一个人的姓和名。您可以有一个订阅这个主题的组件,在任何时候当另一个组件使用一个人的名字发布到该主题时,这将会将这个名字打印到控制台。清单 19 显示了这类订阅的一个示例(在 Firebug 中随意尝试)。
清单 19. 订阅
dojo.subscribe("printName",function(msg) {
console.log("The person's name is: "+msg.first_name+" "+msg.last_name);
});
要发布到该主题,您需要传递一个附带主题 API 的对象数组,(在本例中,对象必须有一个名称和一个姓氏)。清单 20 是一个示例。
清单 20. 发布到一个主题
dojo.publish("printName",[
{
first_name: "Joe",last_name: "Lennon"
}
]);
生成的输出如清单 21 所示。
清单 21. 输出
>>> dojo.publish("printName",[ { first_name: "Joe",last_name: "Lennon" } ]);
The person's name is: Joe Lennon
正如您所看到的,通过发布这个对象到printName
主题,您的订阅函数将相应的一个消息输出到控制台。
回页首
使用 dojo.xhr* 增强 Ajax
创建 Ajax 驱动的 web 应用程序通常是通过创建XmlHttpRequest
(XHR
) 对象完成的,这将向指定的 URL 发出一个 HTTP 请求,传递一个请求头部和正文并定义回调函数,来定义当返回一个成功响应正文或一个 HTTP 失败响应时该完成什么操作。实现跨浏览器 XHRs,至少可以说是很麻烦,但是,谢天谢地,Dojo 使用一组dojo.xhr*
函数极大地减轻了这个令人头疼的麻烦,允许发出GET
、POST
、PUT
和DELETE
请求。
提供如下 4 个函数:
-
xhrGet
-
xhrPost
-
xhrPut
-
xhrDelete
所有这些函数都遵守相同的语法:接受一个属性配置对象作为参数。在这些对象中您可以定义您想要发出的 Ajax 请求的各个方面。再一次说明,这些选项在所有 XHR 函数中都是一样的。
配置选项
XHR函数一些比较有用的配置选项如下:
-
url
-
这是 HTTP 请求的 URL。它必须和发出这一请求的页面有同样的域和端口组合。
-
handleAs
-
允许您定义响应的处理格式,默认是
text
,但是,
json
、
javascript
、
xml
、还有一些其他选项也可用。在本节后面您将看到一个创建 Ajax 请求的示例,使用一个处理 JSON 响应格式的回调函数。
-
form
-
<form>
元素的一个引用或者字符串 ID 表示。form 中每个字段的值将被同请求一起作为请求体发送。
-
content
-
一个对象,包含您想要传递给请求体中资源的参数。如果两者都提供,这个对象将与从
form
属性中获取的值混合在一起。
XHR函数的一个示例如清单 22 所示。
清单 22. XHR 函数调用的示例
dojo.xhrGet({
url: "save_data.php",content: {
id: "100",first_name: "Joe",last_name: "Lennon"
}
});
这将在同一个位置(与文档本身)异步向 save_data.php 文件发出一个 HTTPGET
请求。它也传递内容对象属性到 PHP 脚本作为参数。在 PHP 中,您可以使用$_GET
变量检索这些值,然后可能将它们保存到一个数据库。
回调函数
在之前的示例中,您学习了如何使用dojo.xhrGet
调用一个 Ajax 请求。这个示例对于实际发出请求已经足够了,它不提供设施来处理任何响应。回调函数也被传递到配置对象,下列选项是可用的:
load
-
当 Ajax 请求返回一个成功响应消息时,执行此函数。响应数据和请求对象作为参数被传递到这个函数。
-
error
-
如果 Ajax 请求出现问题,该函数将被调用。如果在 Ajax 请求中定义的 URL 无效、请求超时或者发生其他 HTTP 错误,这将会出现。错误消息和请求对象被作为参数传递。
-
handle
-
该函数允许您将加载和错误回调函数合并到一个函数中(如果您确实不关心请求结果是成功或是出现错误,这将非常有用)。
在下面的示例中,您将使用一个加载回调函数创建一个 Ajax 调用,将从一个 JSON 文件中加载一些值然后打印到页面上。
使用 JSON 数据运行
我们通过创建一个更为真实的示例将dojo.xhr*
函数用来进行一个更好的测试。首先,创建一个新文件 — 将该文件放在与 listing1.html 文件相同的目录下 — 并向其中添加一些 JSON 数据。文件内容如清单 23 所示。
清单 23. data.json — JSON 数据通过一个 Ajax 请求来处理
{
count: 4,people: [
{
first_name: "Joe",last_name: "Lennon",age: 25
},{
first_name: "Darragh",last_name: "Duffy",age: 33
},{
first_name: "Jonathan",last_name: "Reardon",age: 30
},{
first_name: "Finian",last_name: "O'Connor",age: 23
}
]
}
现在,在 Firebug 中创建一个 Ajax 请求(确保 listing1.html 页面被加载到 Firefox 中,这样 Dojo 才可以被加载)。该请求使用load
回调函数处理 JSON 响应,并打印一个表格到页面(见清单 24)。
清单 24. 使用 Ajax 加载并处理 JSON 数据
dojo.xhrGet({
url: "data.json",handleAs: "json",load: function(data) {
var table = "<table border="1">";
table += "<tr><th>Name</th><th>Age</th>
</tr>";
dojo.forEach(data.people,function(person) {
table += "<tr><td>";
table += person.first_name+" "+person.last_name;
table += "</td><td>";
table += person.age;
table += "</td></tr>";
});
table += "</table>";
dojo.place(table,dojo.body());
}
});
在 Firebug 中试一下清单 24 中的代码。一个表格将动态地添加到您的页面上,其中含有从 JSON 文件中加载的数据,如图 5 所示。
图 5. 源自 JSON 文件的加载 Ajax 的表格
在真实的示例中,您可以使用一个服务器端语言(比如 PHP、Python、ASP.NET 或者 Java)、根据通过 Ajax 请求传递给它的参数动态生成 JSON 数据。
回页首
结束语
在这篇从头开始学习 Dojo 的系列文章中,您学习了关于 Dojo 和使用它的基本知识。特别是,您学习了各种 DOM 实用函数、数组函数、事件处理和 HXR 特性,在本系列的下一期中,您将学习如何使用 Dojo 类似 Java? 的基于类的面向对象特性。
转载自:http://www.ibm.com/developerworks/cn/web/wa-ground/
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!