dojostoreMemory 和 SimpleQueryEngine 解读.docx
- 文档编号:13564380
- 上传时间:2023-06-15
- 格式:DOCX
- 页数:14
- 大小:20.54KB
dojostoreMemory 和 SimpleQueryEngine 解读.docx
《dojostoreMemory 和 SimpleQueryEngine 解读.docx》由会员分享,可在线阅读,更多相关《dojostoreMemory 和 SimpleQueryEngine 解读.docx(14页珍藏版)》请在冰点文库上搜索。
dojostoreMemory和SimpleQueryEngine解读
Example:
require(["dojo/store/Memory"],function(Memory){
varsomeData=[
{id:
1,name:
"One"},
{id:
2,name:
"Two"}
];
store=newMemory({data:
someData});
store.get
(1)->Returnstheobjectwithanidof1
store.query({name:
"One"})//根据特定的查询条件,返回符合要求的结果集。
store.query(function(object){
returnobject.id>1;
})//通过传递一个函数来进行查询,可以实现更复杂的查询操作
store.query({name:
"One"},{sort:
[{attribute:
"id"}]})//除了查询以外,返回的结果集会根据id来排序。
store.put({id:
3,name:
"Three"});//保存{id:
3,name:
"Three"}对象,并且放在id:
3的位置。
store.remove(3);//根据ID来删除对象
});
官方API的介绍和切合要点,Memorystore的最显著的特点,就是“简单”。
Memorystore的功能就像上面的例子中的一样,简单暴力,基本齐全。
下面我们根据dojo里的源码进一步解析:
构造函数constructor:
constructor:
function(options){
//summary:
//Createsamemoryobjectstore.
//options:
dojo/store/Memory
//Thisprovidesanyconfigurationinformationthatwillbemixedintothestore.
//Thisshouldgenerallyincludethedatapropertytoprovidethestartingsetofdata.
for(variinoptions){
this[i]=options[i];
}
this.setData(this.data||[]);
},
嗯,我们通过new字段来创建memorystore到对象时,就会调用到这里。
案例中的options参数为{data:
somedata}。
实际上是创建了最最简单的Memorystortt仅仅只用了一个对象数组。
所以当然咯,可以有略复杂一点的情况。
代码中this[i]=options[i],可以看出各种配置都体现在Menory对象的属性里。
下面列一下:
//data:
Array
//Thearrayofalltheobjectsinthememorystore
data:
null,
//idProperty:
String
//Indicatesthepropertytouseastheidentityproperty.Thevaluesofthis
//propertyshouldbeunique.
idProperty:
"id",
//index:
Object
//Anindexofdataindicesintothedataarraybyid
index:
null,
//queryEngine:
Function
//Definesthequeryenginetouseforqueryingthedatastore
queryEngine:
SimpleQueryEngine,
data:
是必须的,如果不存在,会被赋予一个[]空数组。
index:
后续会提到这个属性,它是一个以id("idProperty")为索引的表,表的数据是一个改id对应的属性在data数组里的序号索引。
idProperty:
啊哈,通过这个属性我们可指定改memory的一个不可重复的标识符(字段名),默认是为"id"。
queryEngine:
可以指定memory的搜搜引擎,默认使用的是dojo/store/util/SimpleQueryEngine。
setData:
function(data){
//summary:
//Setsthegivendataasthesourceforthisstore,andindexesit
//data:
Object[]
//Anarrayofobjectstouseasthesourceofdata.
if(data.items){
//justforconveniencewiththedataformatIFRSexpects
this.idProperty=data.identifier||this.idProperty;
data=this.data=data.items;
}else{
this.data=data;
}
this.index={};
for(vari=0,l=data.length;i this.index[data[i][this.idProperty]]=i; } } setData setData可以外部调用,用来更换该Memory的数据源,比如setData([])可以清空。 有一意思的是,从setData的函数体里可以发现,除了官方例子的创建memory的格式,setData还为IFRS开了一个方便之门。 我不太了解IFRS会使用怎么样的数据格式,从代码中可以看出: 1、标识符存放在data.identifier;2、数据存在data.items里。 不过当然的,data.items仍被要求是一个有序对象数组。 我们知道构造函数中数据的初始化也是通过setData实现的,在setData的最后面,实际也是this.index的初始化。 在循环中构建利用this.index[data[i][this.idProperty]]= i;来创建一个以idproperty为索引的散列表。 该散列表保存着对应数据在data里的位置,这样形式的散列表在访问数据时可是非常方便。 get: function(id){ //summary: //Retrievesanobjectbyitsidentity //id: Number //Theidentitytousetolookuptheobject //returns: Object //Theobjectinthestorethatmatchesthegivenid. returnthis.data[this.index[id]]; }, get 通过标识符的值,来获取对应对象。 this.index[id]取出其对应数据的数组位序,然后通过序号去对象数组中取对象。 getIdentity: function(object){ //summary: //Returnsanobject'sidentity //object: Object //Theobjecttogettheidentityfrom //returns: Number returnobject[this.idProperty]; }, getIdentity 获取对象的标识符值。 我们通过它,可以用index[getIdentity(object)]来获取对象在数组中的位置了。 put: function(object,options){ //summary: //Storesanobject //object: Object //Theobjecttostore. //options: dojo/store/api/Store.PutDirectives? //Additionalmetadataforstoringthedata.Includesan"id" //propertyifaspecificidistobeused. //returns: Number vardata=this.data, index=this.index, idProperty=this.idProperty; varid=object[idProperty]=(options&&"id"inoptions)? options.id: idPropertyinobject? object[idProperty]: Math.random(); if(idinindex){ //objectexists if(options&&options.overwrite===false){ thrownewError("Objectalreadyexists"); } //replacetheentryindata data[index[id]]=object; }else{ //addthenewobject index[id]=data.push(object)-1; } returnid; }, put 保存对象。 注意到保存操作是有可选参数的,从源码看看都有些什么。 注意到保存对象id的获取规则: 配置里的“id”字段>对象里的标识符字段>一个随机数字。 如果id已经存在,根据"overwrite"字段,为真则覆盖,假则报错。 如果id不存在,数据存入对象数组最后一位上。 put方法会返回保存对象的标识符值。 add: function(object,options){ //summary: //Createsanobject,throwsanerroriftheobjectalreadyexists //object: Object //Theobjecttostore. //options: dojo/store/api/Store.PutDirectives? //Additionalmetadataforstoringthedata.Includesan"id" //propertyifaspecificidistobeused. //returns: Number (options=options||{}).overwrite=false; //callputwithoverwritebeingfalse returnthis.put(object,options); }, add 保存一个新的对象,可以指定保存的id,但不可覆盖。 其实和put是本质是一样的操作,但更保险,参数overwrite被确定为false。 remove: function(id){ //summary: //Deletesanobjectbyitsidentity //id: Number //Theidentitytousetodeletetheobject //returns: Boolean //Returnstrueifanobjectwasremoved,falsy(undefined)ifnoobjectmatchedtheid varindex=this.index; vardata=this.data; if(idinindex){ data.splice(index[id],1); //nowwehavetoreindex this.setData(data); returntrue; } }, remove 通过标识符值,删除指定对象。 函数体很简单,删除后通过setData更新index的内容。 操作成功会返回true。 query: function(query,options){ //summary: //Queriesthestoreforobjects. //query: Object //Thequerytouseforretrievingobjectsfromthestore. //options: dojo/store/api/Store.QueryOptions? //Theoptionalargumentstoapplytotheresultset. //returns: dojo/store/api/Store.QueryResults //Theresultsofthequery,extendedwithiterativemethods. // //example: //Giventhefollowingstore: // //|varstore=newMemory({ //|data: [ //|{id: 1,name: "one",prime: false}, //|{id: 2,name: "two",even: true,prime: true}, //|{id: 3,name: "three",prime: true}, //|{id: 4,name: "four",even: true,prime: false}, //|{id: 5,name: "five",prime: true} //|] //|}); // //...findallitemswhere"prime"istrue: // //|varresults=store.query({prime: true}); // //...orfindallitemswhere"even"istrue: // //|varresults=store.query({even: true}); returnQueryResults(this.queryEngine(query,options)(this.data)); }, query 强大的query查询功能。 参数可以是字段值,来查询匹配字段的结果;也可以是一个函数,返回真假,来进行复杂的判断。 实际上是调用了memorystore的搜索引擎,这个搜索引擎默认是/util/SimpleQueryEngine。 进一步的,我们去看看SimpleQueryEngine是如何实现搜索的。 首先,模块返回的是一个形参为(query,options)的工具函数。 returnfunction(query,options){ ... } 函数体主要为两部分,第一个switch,第二个execute方法。 switch部分: switch(typeofquery){ default: thrownewError("Cannotquerywitha"+typeofquery); case"object": case"undefined": varqueryObject=query; query=function(object){ for(varkeyinqueryObject){ varrequired=queryObject[key]; if(required&&required.test){ //anobjectcanprovideatestmethod,whichmakesitworkwithregex if(! required.test(object[key],object)){ returnfalse; } }elseif(required! =object[key]){ returnfalse; } } returntrue; }; break; case"string": //namedquery if(! this[query]){ thrownewError("Nofilterfunction"+query+"wasfoundinstore"); } query=this[query]; //fallthrough case"function": //fallthrough } 有四种格式的查询条件可以通过,string,function,object,undefined functiion格式在此直接不处理,往后跑。 string格式为认为是函数体名称,在当前上下文找该函数体。 当query格式为object和undefined时(其实就是object时): 则生成查询函数,查询函数逻辑为,针对object的每一个属性: 1、如果有test方法,则执行test方法; (想到什么了吗? 如果提供的是一个RegExpObject,因持有test方法,则会执行test方法,所以该查询引擎可以支持正则表达式查询) 2、如果没有test方法,则直接进行比较。 总的来说,如果query的格式是一个object,则更像一个复合条件: 举个例子: 假如待查询数据为: data=[ {id: 1,grade: 1,class: 1,peopleNum: 5}, {id: 2,grade: 1,class: 2,peopleNum: 10}, {id: 3,grade: 1,class: 3,peopleNum: 13}, {id: 4,grade: 2,class: 1,peopleNum: 10}, {id: 5,grade: 2,class: 2,peopleNum: 20}, {id: 6,grade: 2,class: 3,peopleNum: 7} ] 假如: query={ test: function(object){ return(object.peopleNum>10} } } //查询结果为对象peopleNum属性大于10的结果,即 //[ //{id: 3,grade: 1,class: 3,peopleNum: 13}, //{id: 5,grade: 2,class: 2,peopleNum: 20} //] 又假如: query={ test: function(object){ rreturn(object.peopleNum>10} }, grade: 2, } //查询结果为对象peopleNum属性大于10,且grade等于2的结果,即 //[ //{id: 5,grade: 2,class: 2,peopleNum: 20} //] 继续往下看,我们看execute部分的内容: 1functionexecute(array){ 2//executethewholequery,firstwefilter 3varresults=arrayUtil.filter(array,query); 4//nextwesort 5varsortSet=options&&options.sort; 6if(sortSet){ 7results.sort(typeofsortSet=="function"? sortSet: function(a,b){ 8for(varsort,i=0;sort=sortSet[i];i++){ 9varaValue=a[sort.attribute]; 10varbValue=b[sort.attribute]; 11//valueOfenablespropercomparisonofdates 12aValue=aValue! =null? aValue.valueOf(): aValue; 13bValue=bValue! =null? bValue.valueOf(): bValue; 14if(aValue! =bValue){ 15return! ! sort.descending==(aValue==null||aValue>bValue)? -1: 1; 16} 17} 18return0; 19}); 20} 21//nowwepaginate 22if(options&&(options.start||options.count)){ 23vartotal=results.length; 24results=results.slice(options.start||0,(options.start||0)+(options.count||Infinity)); 25results.total=total; 26} 27returnresults; 28} 29execute.matches=query; 30returnexecute; 31};
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- dojostoreMemory SimpleQueryEngine 解读