当前位置: 代码迷 >> JavaScript >> extJs 2.1学习札记(Ext.data.JsonReader篇二)
  详细解决方案

extJs 2.1学习札记(Ext.data.JsonReader篇二)

热度:148   发布时间:2012-11-22 00:16:41.0
extJs 2.1学习笔记(Ext.data.JsonReader篇二)

?有了上一篇中所讲内容,一般情况下就可以应付了,不过,JsonReader有一些细节问题,还要细究。待某家一一道来。
  构造函数已讲,下面依代码顺序讲解了。

??? read : function(response){
??????? var json = response.responseText;
??????? var o = eval("("+json+")");
??????? if(!o) {
??????????? throw {message: "JsonReader.read: Json object not found"};
??????? }
??????? return this.readRecords(o);
??? },

  这个是整个JsonReader的关键所在了。君可找到Ext.data.HttpProxy中的loadResponse函数,里面有这么一行代码:

  result = o.reader.read(response);

  可见,是proxy里面调用reader.read方法才得以取出结果集的。这是要表明:read乃JsonReader三军中军之所在。 read又调用readRecords,read把json字符串转化为对象然后交给readRecords。这个本无不妥,但是,asp.net中,它的结果有点曲折,结果是放在o.d中,而不能直接从o中取得。所以,事实上应当这么写:this.readRecords(o.d)。这就成了。继续往下面看:

??? onMetaChange : function(meta, recordType, o){

??? }

  这个函数说是要由store实现的,现在不知道它的用处。还往下看:
??? simpleAccess: function(obj, subsc) {
???? return obj[subsc];
??? },
??? getJsonAccessor: function(){
??????? var re = /[\[\.]/;
??????? return function(expr) {
??????????? try {
??????????????? return(re.test(expr))
??????????????????? ? new Function("obj", "return obj." + expr)
??????????????????? : function(obj){
??????????????????????? return obj[expr];
??????????????????? };
??????????? } catch(e){}
??????????? return Ext.emptyFn;
??????? };
??? }(),

  取一对象的属性有两种方法,前面都已提及:

  一、obj.xxxx

  二、obj[xxxx]

  这两种都行。但是,如果传过来一个对象,已知其对象的引用obj,但是有的只是它的属性名的字符串,这时就可以用第二种方法取出,但是,如属性名中含[],那么就不大方便了,又或者是属性又带属性,这事也只能用第一种方法。这两个函数正是为事而来。且看那getJsonAccessor,着实巧妙,函数返回一函数,这不是巧妙之处,这个我以前就见识了,关键在于new Function("obj","return "obj."+expr)。多么巧妙啊。此之中巧,不足以言语道哉。

  这下面就是真正的好戏了,看一看readRecords函数。

??????? this.jsonData = o;
??????? if(o.metaData){
??????????? delete this.ef;
??????????? this.meta = o.metaData;
??????????? this.recordType = Ext.data.Record.create(o.metaData.fields);
??????????? this.onMetaChange(this.meta, this.recordType, o);
??????? }

  定义一个jsonData属性以保存原始json对象。然后如果传过的json对象中就有metaData。那么,就用它自带的meta来取代JsonReader构造函数中所传入的meta。以原来自带的为主。这个功能方档未曾提及,但我辈不可不察也。

??????? var s = this.meta, Record = this.recordType,
??????????? f = Record.prototype.fields, fi = f.items, fl = f.length;

  有人不理解了,为什么非得这样呢?这是节省带宽啊。如果这些东西以后多说现几次,那么每个用户都要多下载一些东西,成千上万人能节省多少啊。

??????? if (!this.ef) {
??????????? if(s.totalProperty) {
???????????? this.getTotal = this.getJsonAccessor(s.totalProperty);
???????? }
???????? if(s.successProperty) {
???????????? this.getSuccess = this.getJsonAccessor(s.successProperty);
???????? }
???????? this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
???????? if (s.id) {
????????? var g = this.getJsonAccessor(s.id);
????????? this.getId = function(rec) {
?????????? var r = g(rec);
?????????? return (r === undefined || r === "") ? null : r;
????????? };
???????? } else {
????????? this.getId = function(){return null;};
???????? }
??????????? this.ef = [];
??????????? for(var i = 0; i < fl; i++){
??????????????? f = fi[i];
??????????????? var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
??????????????? this.ef[i] = this.getJsonAccessor(map);
??????????? }
??????? }

  因为要根据meta.id、meta.root。这两值都是字符串,这就要用到前面定义的getJsonAccessor函数了。这儿正是来生成几个取json对象中属性的函数,如:getTotal、getSuccess、getRoot、getId、ef数组,一个ef数组就解决了属性映射的问题,真是漂亮。

???? var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
???? if(s.totalProperty){
??????????? var v = parseInt(this.getTotal(o), 10);
??????????? if(!isNaN(v)){
??????????????? totalRecords = v;
??????????? }
??????? }
??????? if(s.successProperty){
??????????? var v = this.getSuccess(o);
??????????? if(v === false || v === &apos;false&apos;){
??????????????? success = false;
??????????? }
??????? }

  这儿是求totalRecords、success。有一事要注意:其中:

  c = root.length, totalRecords = c

  这上c后面要用来循环的,而totalRecords是要返回的,而后,又求了totalRecords,这个意思是:如果结果中没有 totalProperty这一属性,那么就自动求取,如果存在,则以定义的totalProperty为主,由此可见,totalProperty是可有可无的。这个问题文档不曾见之。诸位可无忧矣。

???? var records = [];
???? for(var i = 0; i < c; i++){
????? var n = root[i];
???????? var values = {};
???????? var id = this.getId(n);
???????? for(var j = 0; j < fl; j++){
???????????? f = fi[j];
??????????????? var v = this.ef[j](n);
??????????????? values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, n);
???????? }
???????? var record = new Record(values, id);
???????? record.json = n;
???????? records[i] = record;
???? }
???? return {
???????? success : success,
???????? records : records,
???????? totalRecords : totalRecords
???? };

  这是剩余的代码了,由for(var i = 0; i < c; i++)可知,循环的时候还是用root.length的。而不是totalProperty。这个要分清,事实上,totalProperty只是直接返回罢了,未做任何改动。里面就转化成Record了。其中,这个ef数组用得巧妙。类型转化用了convert。这个东西前文已讲,不足道哉。

  var record = new Record(values, id);

  id=this.getId(n),可见啦,id并非前文所说的主键,它只是一个用来做客户端唯一编号的东西,如对此有疑,可见于Ext.data.Record类。

  record.json = n,json这个属性我在Ext.data.Record类中并未曾得见,诸君注意了,这个东西也许会有用。另外,readRecords返回的不只是一个records数组,而是一个json对象,包含success、records、totalRecords。

  至此,JsonReader源代码分析完毕,呵呵,因为这个类代码量较少,故讲得详细。

  相关解决方案