Dojo Data Store——统一数据访问接口摘要:本
文的目的就是为了介绍Dojo的数据处理模块:Dojo.data。作为Dojo的数据处理中间层,其主要的职责就是解析及管理由数据源传入的各种类型的
数据,通过统一的数据访问与处理接口与数据展现层(Dojo Widget)进行通讯,便于各个Widget的管理与程序的移植。
无论在传统的桌面应用还是在主流的互联网应用中,数据始终占据着软件应用中的核心地位。当下,web2.0已经是一个让人们耳熟能详 的词汇,而由此带来的数据的开放与共享,引领我们走入了海量数据时代。在今天的互联网上,数据的交互几乎成为了我们的终极诉求,可随之而来的数据多样性, 信息的分布式存储及松耦合,以及数据量的几何级规模的膨胀也带来了数据组织上的难度的增大,与此同时,伴随着Ajax, RIA及面向服务的网络应用的发展,其所要求的客户端数据处理逻辑的复杂性不断增加,使得开发难度不断加大。 出于简化数据处理逻辑,增加应用的可维护及可扩展性的需求,目前流行的JavaScript框架也基本都会具有各自的数据处理模块或接口。本文 的目的就是为了介绍Dojo的数据处理模块:Dojo.data。作为Dojo的数据处理中间层,其主要的职责就是解析及管理由数据源传入的各种类型的数 据,通过统一的数据访问与处理接口与数据展现层(Dojo Widget)进行通讯,便于各个Widget的管理与程序的移植。 Dojo Data中的数据管理在面向服务应用大行其道的今天,协调数据的多样性是开发互联网应用中不可避免的首要问题。我们常见的数据格式包括Json, XML, Csv等,作为数据处理的中间层,能够让用户以统一的接口连接不同的数据源是一个基本需求。在Dojo.data模块中,预定义了不同的 DataStore用于访问管理不同数据格式的数据源,而所有的DataStore都会实现相同的数据访问接口,这样就可以成功实现数据提供层与数据展现 层之间的松耦合。表1中列出了Dojo中部分已实现的各种不同的DataStore。 表1. Dojo中部分已实现的DataStore
尽管读取的数据源多种多样,但在DataStore中,通过统一数据访问接口,对数据的组织管理是一致的。每条数据项都被作为一个item对 象,其中包含了一定的键(attribute)值(value)对用以对应数据条目中的各个属性值。下面以一段简单的JSON数据片段为例,来介绍这种对 应关系: {
identifier: 'id', label: 'name', items: [ { "id": "AF", "name":"Africa", "type":"continent", "population":"900 million", "area": "30,221,532 sq km" }, { "id": "AS", "name":"Asia", "type":"continent", "population":"1 billion", "area": "25,428,192 sq km" } ] } 在这段JSON数据中共有两条数据项(item),分别都包含有"id", "name", "type", "population"与"area"五个属性字段。 Dojo.data 组织架构为了符合各种应用中对数据中间层的不同需求,Dojo.data包对数据访问处理接口进行了一定程度的划分,包括 read,write,identify,notifaction 等。各种DataStore可以根据其应用需求实现特定的接口。 表2. Dojo.data.api主要接口
Dojo.data API简介Read数据的获取是数据中间层的核心,Dojo.data.Read接口为异步获取异构数据提供了很大的便利性和灵活性。在Read接口中,主要是通过异步方式进行数据的获取,同时也提供了数据的排序、分页、简单查询等基本功能的支持。 fetch: function(/* Object */ keywordArgs)
fetch方法可以说是Dojo.data包的核心方法,它主要采用异步方法来获取数据。该方法接收一个键值对对象参数,用户可以通过对此参数中各个属性进行指定以获取特定的数据集合,如分页,简单查询过滤,排序等。以下是部分主要的参数属性介绍:
WriteDojo.data.Wirte接口主要提供了数据的更新功能API,包括创建、删除、更新数据。同 Read 接口类似,Write API 的设计目标也是屏蔽底层数据存储格式的差异,为用户提供统一的数据访问 API。借助这些 API,用户可以专注于业务层面的逻辑实现,而无需花费太多精力去关注底层数据的存储格式。
Notification当DataStore中有数据更新时,相应的Notification中定义的监听函数就会被调用。使用过Dojo的读者可 能都会注意到,在Widget中一般不会有new、delete等其他JavaScript库控件中常见的API。这是因为Dojo data的设计是力求将数据层与表现层进行分割,对数据的操作都集中在数据层进行控制,而数据集的改变也能够自动的在应用控件上进行反映,这一功能就是当 DataStore在进行数据更新操作时,通过Notification接口的通知作用实现的。
Identify很多数据源都会为数据提供唯一的标识符,Dojo.data.Identify接口则提供了基于唯一标识符进行数据获取定位的API支持。
DataStore应用一般来说,Dijit中的各个小部件都提供了对DataStore的支持,当我们在使用某个Widget来进行数据展现时,通常我们只需要根据 数据源的格式类型来选择好DataStore,然后在Widget声明中对DataStore进行指定就可以了。下面我们就通过DataGrid及 ComboBox作为数据展现UI,基于不同的数据格式为它们设置不同的DataStore。 以下是一份JSON数据: data = {
identifier: 'id', label: 'name', items: [ { "id": "AF", "name":"Africa", "type":"continent", "population":"900 million", "area": "30,221,532 sq km" }, { "id": "AS", "name":"Asia", "type":"continent", "population":"1 billion", "area": "25,428,192 sq km" }, { "id": "OC", "name":"Oceania", "type":"continent", "population":"21 million", "area": "15,928,294 sq km" }, { "id": "EU", "name":"Europe", "type":"continent", "population":"56 million", "area": "25,928,294 sq km" }, { "id": "NA", "name":"North America", "type":"continent", "population":"100 million", "area": "90,928,294 sq km" }, { "id": "SA", "name":"South America", "type":"continent", "population":"102 million", "area": "78,928,294 sq km" }, { "id": "AN", "name":"Antarctica", "type":"continent", "population":"998", "area": "102,928,294 sq km" } ]}; 在这里,我们采用比较简单的dojo.data.ItemFileReadStore: var jsonStore =new dojo.data.ItemFileReadStore({data: data});
ItemFileReadStore比较适合于处理数据量较小的数据源,数据源可以是一个JSON文件或者象本例一样直接指定到客户端内存中的一组数据。当你使用更加大型的JSON数据集时,可以使用JsonRestStore,采用Rest服务来进行数据提供。 接下来,我们来声明一个DataGrid。在这里DataStore是通过”store”属性进行设置的。 <table jsid="grid" store="jsonStore" query="{name:’*'}" dojoType="dojox.grid.DataGrid" class="grid">
<thead> <tr> <th field="name" width="auto">Name</th> <th field="population" width="auto">Population</th> <th field="area" width="auto">Area</th> </tr> </thead> </table> 生成的DataGrid如下图所示: 由于Dojo中对数据展现层与数据中间层的松耦合,同样一份数据源可以在不进行任何处理的情况下为多个Widget提供数据,而且由于数据的过 滤、排序、分页都是根据数据获取请求按需返回的,使用相同 DataStore的多个Widget间也不会产生冲突。下面我们就以同样的DataStore,为一个dijit.form.ComboBox提供数 据: <input dojoType="dijit.form.ComboBox" store="jsonStore" searchAttr="name"></input>
在很多实际应用中,可能会使用不同的数据源,下面,我们采用不同的数据格式,以XmlStore来替换ItemFileReadStore。首先将JSON数据转换为XML数据格式: <continents>
<continent> <name>Africa</name> <population>900 million</population> <area>30,221,532 sq km</area> </continent> <continent> <name>Asia</name> <population>1 billion</population> <area>25,428,192 sq km</area> </continent> <continent> <name>Oceania</name> <population>21 million</population> <area>15,928,294 sq km</area> </continent> <continent> <name>Europe</name> <population>56 million</population> <area>25,928,294 sq km</area> </continent> <continent> <name>North America</name> <population>100 million</population> <area>90,928,294 sq km</area> </continent> <continent> <name>South America</name> <population>102 million</population> <area>78,928,294 sq km</area> </continent> <continent> <name>Antarctica</name> <population>998</population> <area>102,928,294 sq km</area> </continent> </continents> XmlStore是一个客户端的数据存储器,用于读取XML数据源。它由Dojo官方提供并包含在DojoX子项目中。XmlStore为基本 的XML数据(一种常用的数据交换格式)提供读/写接口。XmlStore可以用于一般的XML文档,因此非常有用。存储器的设计是你可以通过覆盖其部分 方法来自定义读/写数据的行为。下面的示例给出了如何创建XmlStore并将其应用到Grid及ComboBox中: var xmlStore =new dojox.data.XmlStore({
url: ‘continents.xml’, label: ‘name’ }); <table jsid="grid" store="xmlStore" dojoType="dojox.grid.DataGrid"class="grid"> <thead> <tr> <th field="name" width="auto">Name</th> <th field="population" width="auto">Population</th> <th field="area" width="auto">Area</th> </tr> </thead> </table> <input dojoType="dijit.form.ComboBox" store="xmlStore" searchAttr="name"> 我们几乎不需要修改关于Grid和ComboBox的任何代码,就能让它们继续工作。唯一需要做的改动,就是声明一个数据源,并将它设置为grid的输入。我们不需要操心任何关于数据获取、解析、以及管理的事情,数据存储器的API做了所有的工作。 可以看出,作为数据中间层,Dojo.data通过优秀的API设计充分达成了数据展现层与数据管理层之间的松耦合,同时统一的数据访问接口使得对多种数据格式的应用以及程序移植都带来了相当大的便利性。 |
|