首页 / 脚本样式 / Dojo Toolkit / 使用Dojo的Ajax应用开发进阶教程,第7部分: Dojo核心库深入介绍
使用Dojo的Ajax应用开发进阶教程,第7部分: Dojo核心库深入介绍2011-01-21 IBM 成富Dojo 核心库构建于 Dojo 基本库之上,为 Ajax 应用的开发提供了更加丰富的功能。掌握 Dojo 核心库中包含的内容,可以开发人员减少代码量,而把工作精力集中在与业务逻辑相关的组件的实现上。Dojo 核心库中包含的内容也比较多,本文只是介绍其中一些比较重要或是复杂的部分。首先从数据模型开始介绍。数据模型在传统的 Web 应用中,客户端部分所承担的职责很少,基本上只负责数据展现。应用所涉及的复杂数据模型的处理工作由服务器端代码来完成。而在 Ajax 应用中,客户端部分也需要处理一部分的业务逻辑,其中就包括数据模型的处理。复杂用户界面组件,如表格、树等的出现,也要求客户端能够处理组件后台复杂的数据模型。一般的 Ajax 应用都会使用复杂的 JSON 对象作为其客户端的数据模型,由应用自己来维护此模型。这样造成的问题是维护的代价过高,不同的模型之间无法方便的共享数据。Dojo 核心库中提供了 dojo.data模块用来解决这个问题。它定义了一些数据访问和操作的标准接口,以及相关的实现。数据消费者都使用同样的接口来访问和操作数据,提高了它们之间的互操作性。统一的接口也使得开发人员的代码可移植性更好。开发人员也不需要学习和理解很多私有的数据访问接口和协议。dojo.data对数据的抽象非常简单。负责管理数据的是数据仓库(data store),它是条目(item)的集合。而条目则是属性(attribute)的集合。这个抽象在概念上类似于关系数据库中的表。关系数据库中的表是行的集合,而行是字段的集合。关键的不同在于,关系数据库中表的行是同构的,包含相同的字段;dojo.data中的条目可以是异构的,包含完全不同的属性。dojo.data的 API 都围绕这个抽象展开。其中包含了 4 类 API,分别是读(dojo.data.api.Read)、写(dojo.data.api.Write)、标识符(dojo.data.api.Identity)和通知(dojo.data.api.Notification)。读和写的 API 分别用来对数据仓库中的条目进行读取和更新操作。标识符 API 用来为数据仓库中的每个条目提供惟一的标识符,并可以通过此标识符来获取条目。通知 API 用来在数据仓库中的条目发生变化的时候得到通知,这些变化包括条目的创建、删除和属性的更新等。限于篇幅,本文并不会详细介绍 dojo.data的全部 API 的细节,而是讨论一些需要注意的地方与最佳实践。在 dojo.data.api.Read接口中的 fetch()方法是异步执行的,需要传入回调方法。即便数据仓库中的条目都是可以从本地获取的,也是需要使用回调方法。从 API 的角度来说这是必须的,不过可能会造成一些代码编写时候的麻烦。通过与 dojo.Deferred配合起来使用,可以简化代码的编写。当 dojo.data数据仓库作为用户界面组件后台的数据来源时,dojo.data.api.Notification API 非常有用。它可以用来实现典型的观察者设计模式。当数据仓库中的数据发生改变时,用户界面组件也需要相应的更新。使用 dojo.connect()连接到数据仓库的 onNew()、onDelete()和 onSet()方法上,就可以在创建条目、删除条目和更新条目属性的时候得到通知。这里需要注意的是当一个条目被删除的时候,在 onDelete()方法中可以得到该条目的对象,但是该条目已经不属于原来的数据仓库了,不能再通过 getValue()等方法来获取条目中的属性。onSet()在每个属性更新的时候都会被调用。如果同时更新了条目的多个属性,需要注意 onSet()方法的重复调用。Dojo 核心库提供了两个基于 JavaScript 对象的数据仓库的实现 dojo.data.ItemFileReadStore和 dojo.data.ItemFileWriteStore。这两个仓库可以作为服务器端返回的数据与 Dojo 用户界面组件之间的桥梁。很多 Dojo 用户界面组件,如表格、树和下拉列表等,都使用 Dojo 数据仓库作为其后台数据模型。一般的做法是从服务器端数据中创建出一个 dojo.data.ItemFileReadStore,提供给这些用户界面组件使用。dojo.data.ItemFileWriteStore还可以作为 JavaScript 数组的良好替代。Ajax 应用中通常会使用数组来维护内部的领域对象。使用数组在查找、更新和删除对象时不太方便,一般需要添加额外的代码。使用 dojo.data.ItemFileWriteStore可以很好解决这个问题。它提供的通知 API 的支持,也能帮助编写更加简洁的代码来处理对象的变化。在使用这两个数据仓库的时候,需要注意 JavaScript 对象中的数组类型的属性的存取方式。对于数组里面包含的多个元素,需要通过 getValues()方法才能读取出来。如果使用 getValue()方法的话,只能读取到数组的第一个元素。如果希望能够统一成使用 getValue()方法,则在该数组存放到数据仓库之前,需要把它转换成只有一个元素的新数组。代码清单 1 中给出了在数据仓库中的条目和 JavaScript 对象之间相互转换的示例。清单 1. 在数据仓库中的条目和 JavaScript 对象之间相互转换var item = {
name : "Alex",
skills : ["JavaScript", "Java"]
};
function addJsonToStore(store, json) {
for (var key in json) {
if (json.hasOwnProperty(key) && dojo.isArray(json[key]) {
json[key] = [json[key]];
}
}
store.newItem(json);
}
function storeItemToJson(store, item) {
var attrs = store.getAttributes(item);
var result = {};
dojo.forEach(attrs, function(attr) {
result[attr] = store.getValue(item, attr);
});
return result;
}
如 代码清单 1 所示,addJsonToStore()方法对 JavaScript 对象中的数组进行了处理。在通过 storeItemToJson()方法把数据仓库中的条目转换成 JavaScript 对象的时候,就可以直接使用 getValue()方法而不会出现错误。在介绍完 Dojo 核心库提供的数据模型之后,下面介绍与 I/O 请求相关的内容。