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 === 'false'){
                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源代码分析完毕,呵呵,因为这个类代码量较少,故讲得详细。

你可能感兴趣的:(C++,c,json,ext,F#)