阿木申 申楠

热衷编程技术 | 申楠 : qq:38371354 | msn:amushen2005@hotmail.com

导航

dojo0.9 dojo.data研究笔记

Posted on 2007-07-18 10:51  阿木申  阅读(1131)  评论(0编辑  收藏  举报
dojo0.9的store核心内容。
最近研究了一些,也翻译了一些,贴出来和大家分享。dojo的更多内容可以上: www.dojocn.cn 上查看。

一下内容是原创,转载请注明:

dojo.data 是什么?

 

dojo.data 是一个统一的数据访问层,它没有数据库驱动的概念,只是一个统一的数据格式.

所有的数据被表现成一个 item item 或者 attribute , 由于这样,数据就能够被统一的方式访问.

 

为了直接拿来就可以用,dojo.data提供了一个基础的 JsonItemStore 去读一个特定格式的JSON 数据.

DojoX 这个项目(或者说是模块)提供了更多的 stores (比如:XmlStore , CsvStore , OmplStore),这些stores可以解决服务器提供的对应的这些格式的数据.

 

此外,dojo.data是一个其他用户可以重写的API,这个概念类似java中的接口,因此,你可以编写一个定制数据格式的dojo.data的一个子集.

当你的定制好自己的特定格式,而且按照dojo.data的规范来做,widgets 就可以直接知道你的datastore,并且其他的程序可以读取你的数据,而不用了解你的特定格式.

 

dojo.data的最终目标是提供一个易用灵活的API,就像interfaces.使datastore按照统一的格式被定制或者重写.

按照标准接口写的store就能够被多样的广泛的应用程序或者widget等等使用.

本质上,API隐藏了特定格式的数据,这些格式在JSON,XML,Csv或者其他数据格式,并且提供了一个一致的读itemattribute的方法,并且,用户可以根据实际的使用情况定制最优化的方法读取数据.(这一句翻译的不好)

 

你可以理解dojo.datadojo.xhrGet()(这个封装了XMLHttp发送请求到服务器)上的一层,他们都是不用刷新页面的异步操作.但是xhrGet将能够读取任何MIME类型的数据并且一下子都返回,然后就依靠store去翻译这些数据成需要的格式,从而形成一般的读取模型.

 

综上:dojo.data提供了一套统一的读取数据的方法,它的目的就是提供一个标准,大家按照这个标准来开发读取数据的方法.

dojo.data对页面组件关系非常密切,比如TreeCombox都使用了store做为数据源.所以学好这个对灵活使用widget很有帮助

 

=========================================================================================================================

dojo.data 术语

 

dojo.data 术语类似关系型数据库术语,下面比较和对比了dojo.data术语和关系型数据库的术语:

 

dojo:datastore

db:cursor

描述:js对象通过dojo.data APIsdata source读取数据并且使 data item可用

 

dojo术语:data sorece

db术语:table

描述:这是保存原始数据的地方,比如:一个CsvStore数据源可能是.csv格式的文件,通常,data source是一个文件或者是个数据库服务器,或者是一个webservice或其他

 

dojo术语:item

db术语:row

描述:data item有很多属性,这些属性都有值

 

dojo术语:attribute

db术语:column

描述:一个item的域或者属性.

 

dojo术语:value

db术语:-

描述:属性的内容

 

dojo术语:reference

db术语:-

描述:一个item指向另一个item的值

 

dojo术语:identity

db术语:primary key

描述:主键

 

dojo术语:query

db术语:Where字句

描述:读取数据的条件.注意:非常建议所有的store使用attributename/value成对的结构,作为查询的格式连接stores.

 

internal data representation:一个私有的数据结构,datastore用它来缓存数据到客户端,比如XML DOM节点,匿名JSON对象或者数组

 

dojo术语:request

db术语:Sql Select

描述:一个用来筛选item的参数,包括query,筛选attributes ,大小写的限制和回调函数

 

=============================================================================================================================

 www.dojocn.cn 转载请注明

dojo.data 设计和编程接口

 

在直接学习dojo.dataAPI之间,在研究API之前的基本概念必须先探究一下,因为一些设计上的决定被选择,但却没有解释为什么选择它们,可能会使这个设计看上去很奇怪。因此,在研究api细节之前,先完整的阅读这些概念:

 

概念1:数据访问被分成分离的APIsstore可以有选择的实现这些API

数据访问被破坏成分离的APIs,因为不是所有的服务和数据回传都需要所有的访问或者函数。因此不是所有的datastore能够实现比如read,write,identify,notifications这样的函数(注意这里的函数是jsfunction,在这里可以想像成java的接口)。

为了能够简单的就知道这个store提供什么特性,每一个store必须提供getFeatures()这个函数,这个函数报告出这个store使用了哪些APIs

下面是基础的APIs定义:

dojo.data.api.Read:能够从一个dataitems里读取子itemsattribute。而且可以查询,排序,过滤数据。

 

dojo.data.api.Write:能够生成、删除、更新dataitemsattribute。不是所有的服务都允许修改数据项的。实际上,大多数公共的服务,比如:Flikr,Delicious还有googleMaps都只是提供读取服务。

 

dojo.data.api.Identity:能够通过唯一标识定位查找一个数据项,不是所有的数据服务有唯一标识的。

 

dojo.data.api.Notification:能够将发生在store上的数据修改事件通知给监听器。基础的功能是那些生成、删除、更新一个数据项的事件。对于像定期将数据更新的事件通知backend服务有显著的用处。

 

将来的一些特性:

下面的特性是一些dojo开发团体将会定义的额外的特性,这些都还没有完全明确,并且还在开发中。因此,他们没有被提供在当前版本的开发包中。注意啊,下面的列表可能随时变化。

dojo.data.api.Schema

dojo.data.api.Attribution

dojo.data.api.Versioning

dojo.data.api.Derivation

  www.dojocn.cn 转载请注明

概念二:数据项和数据项的属性经常通过store的函数来访问,修改,创建和删除,而从来不直接访问。

这个概念就是防止dojo.data在最初的时候表现出来混乱,下面的例子显示了这个概念:

---------------------------------------------------------------------------------

var store = new some.data.Store();

 var items;

 .......

 //假设这时items已经通过store.fetch()得到了数据,成为了array

 //为了列举出这个数组的值,你要这样做:

 for(var i=0;i<items.length;i++){

   var item=items[i];

   console.log("For attribute 'foo' value was:["+store.getValue(item,"foo")+"]");

 }

----------------------------------------------------------------------------------

为什么不像下面这样做呢?

 var value=item["foo"];

 var value=item.foo;

 var value=item.getValue("foo");

 

为什么这是dojo.data必须要求的呢?下面是原因:

1、访问效率。通过store的函数访问,store可以隐藏item的内部结构,无论在什么特殊形式下的数据格式,item都能保持一个格式.比如:

item可能是一个XML元素,这种情况下,当调用store.getValue()store将使用DOMAPI来访问数据;另外一种情况下,如果item是个一个javascript结构,那么store将通过javascript的访问符号来访问数据.从最终用户的角度来看,这个访问都是一样的:store.getValue(item,"attribute"),因此提供了一个统一的感观去访问多样的类型数据.通过减少item的加载次数,也提高了访问item的效率,因为你不用每次都转换格式了.

 

2store可以使用非常简洁的内部结构。这大大减少了程序员记忆每种数据格式的工作量。

 

3、能够提供懒加载的模式

=======================================================================================

 

 

The Read API

Dojo.data 中最基础的API(或者说是接口)就是Read API. 所有的Store都必须实现这个接口,因为所有的store都需要获取和处理item(数据项)。针对处理数据项,Read API被设计的非常灵活。Read API提供如下的功能:

l         查看datastore都实现了那些接口,具有什么功能。通过getFeatures()方法。

l         查看一个item所包含的所有属性而不需要了解这个item的格式。getAttributes(item)方法

n         比如:一个item记录着一个学生的信息。通过getAttribuets()方法,你能得到这个学生包括哪些信息,比如:姓名,学号,等等。

l         获取item的属性的值,而不用知道item的格式。

n         Item的保存格式有很多中,有json或者csv或者数据库中保存。通过getValue方法,你就能得到一个item的属性的值,转换数据格式交给store来做。

l         查看所有的items的属性,看看有没有指定的值。

l         验证一个js Object是不是store产生的item.

l         查看一个item是不是被完全加载了,还是仅仅是一个需要被加载的根(stub). isItemLoaded()

l         加载一个stub item ,这个方法就是懒加载的时候使用的。loadItem()

l         通过一些查询条件来查询items

l         给一些items排序

l         为一个查询结果分页。(我觉得对非数据库型的查询也许会有用一些,至少能使操作方便一些吧)

l         通过通配符( * ? )来过滤查询结果

  www.dojocn.cn 转载请注明

一些例子:

1、  查看一个store支持那些APIs

var store = new some.Datastore();

var features = store.getFeatures();

for(var i in features){

    console.log("Store supports feature: " + i);

}

 

2、  测试一个对象是不是一个item

var store = new some.Datastore();

if(store.isItem(someObject)){

    console.log("Object was an item.");

}else{

    console.log("Object was NOT an item.");

}

 

3、  列举一个item的所有属性

var store = new some.Datastore();

...

//Assume that someItem is an item we got from a load.

var attributes = store.getAttributes(someItem);

for(var i = 0; i < attributes.length; i++){

    console.log("Item has attribute; " + attributes[i]);

}

 

4、  测试一个item是否包含特定的属性

var store = new some.Datastore();

...

//Assume that someItem is an item we got from a load.

var attributes = store.getAttributes(someItem);

for(var i = 0; i < attributes.length; i++){

    console.log("Item has attribute; " + attributes[i]);

}

 

5、  得到一个itemlabel


       var store = new some.Datastore();

...

//Assume that someItem is an item we got from a load.

var label = store.getLabel(someItem);

console.log("item has label: " + label);

 

//其实一个itemlabel也是一个item的属性,只不过是一个特殊的属性。在json的开始部分:label:”name” 这个就声明了,itemname属性就是itemlabel,所以通过getLabel就得到了name属性,也就等同于getValue(item,”name”);

 

6、得到一个store的所有数据

var pantryStore = new dojo.data.JsonItemStore({url: "pantry_items.json" } );

 

//Define the onComplete callback to write COMPLETED to the page when the fetch has finished returning items.

var done = function(items, request){

    document.appendChild(document.createTextNode("COMPLETED"));

}

 

//Define the callback that appends a textnode into the document each time an item is returned.

gotItem = function(item, request) {

    document.appendChild(document.createTextNode(pantryStore.getValue(item, "name"));

    document.appendChild(document.createElement("br"));

}

 

//Define a simple error handler.

var gotError = function(error, request){

    alert("The request to the store failed. " +  error);

}

 

//Invoke the search

pantryStore.fetch({onComplete: done, onItem: gotItem, onError: gotError});   

//这里onCompleteonItem同时使用的时候onCompleteitems参数是null,这点请注意。

 

6、  通过一个标识得到一个item

var pantryStore = new dojo.data.JsonItemStore({url: "pantry_items.json" } );

   var pepperItem = pantryStore.getItemByIdentity("pepper");

   if (pepperItem !== null){

        alert('Pepper is in aisle ' + pantryStore.getValue(pepperItem,"aisle");  

   }

       //这个标识在json的开头部分有声明, identifier: 'name' ,也就是说itemname属性是标识。

 

7、  通过条件获取数据

jsonItemStore.fetch({

        queryOptions: {ignoreCase: true},  //忽略大小写

        query: { name: "*pepper*", aisle: "Spices" }, //name aisle是属性的名称

        onComplete:

                ...  

   });

8、  嵌套定义item

一个item可以包括多个子item就像一棵树一样。使用reference可以关联子节点。通过getValues()方法可以得到孩子节点的数组。

 

9、  分页

    var store = new dojo.data.JsonItemStore({url: "pantryStore.json" });

    var pageSize = 10;

    var request = null;

    var outOfItems = false;

 

    var onNext = function(){

       if(!outOfItems){

           request.start += pageSize;

           store.fetch(request);

       }

    };

 

    var onPrevious = function(){

       if (request.start > 0){

          request.start -= pageSize;

          store.fetch(request);

       }

    }

    var itemsLoaded = function(items, request){

       if (items.length < pageSize){

       

          outOfItems = true;

       }else{

          outOfItems = false;

       }

       ...

    }

 

request = store.fetch({onComplete: itemsLoaded, start: 0; count: pageSize});

 

10、              排序

var store = new dojo.data.JsonItemStore({url: "pantryStore.json"});

 

var sortKeys = [

    {attribute: "aisle", descending: true},

    {attribute: "name", descending: false}

];

 

store.fetch({

       sort: sortKeys;

       onComplete:

           ...

});

//When onComplete is called, the array of items passed into it

//should be sorted according to the denoted sort array.
 www.dojocn.cn 转载请注明