zoukankan      html  css  js  c++  java
  • 48.EXt.Data.JsonReader()

    转自:https://blog.csdn.net/huoyanxueren/article/details/2662915?utm_source=blogxgwz6

    extJs 2.1学习笔记(Ext.data.JsonReader篇一)

      有个事要说一下:DataProxy的子类呢,都有一个load来加载数据,DataReader的子类呢,都有一个read来读取数据。

      而Ext.data.JsonReader有两个关键函数:read、readRecords。好了。来研究一下。

      Ext.data.JsonReader = function(meta, recordType){
       meta = meta || {};
       Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
      };

      这是构造函数。简单。meta是数据格式定义,recordType是记录类型。其中recordType可以是一个定义记录的数组,也可以不传,而把记录的各个字段的定义放到meta中的fields字段中。且看它对父类构造函数的调用:

      Ext.data.DataReader = function(meta, recordType){
       this.meta = meta;
       this.recordType = Ext.isArray(recordType) ?
       Ext.data.Record.create(recordType) : recordType;
      };
      Ext.data.DataReader.prototype = { };

      这下全明白了吧。recordType可以是记录类型,可以是字段定义数组,还可以不传。

      所以,构造函数就是定义两个属性:meta、recordType。这两东西后面有用。

      这个meta、recordType组成如何?这个必须说明,不然,这个类也就没法用了。

      meta:

      totalProperty    json数据中,保存总记录数的属性

      successProperty   json数据中,保存是否返回成功的属性名

      root        json数据中,保存记录集的属性的属性名

      id         json数据中,记录中主键所对应的列的属性名

      recordType:

      这个东西,事实上要去看Ext.data.Record的create函数的文档,我且把它翻译一下,如下:

    create( [Array o] ) : function

    创建包含指定字段结构的继承自Ext.data.Record的类。静态方法。

    参数:
      o : Array
    一个定义记录结构的字段信息数组。每个数组元素包含name,其他可选的有:mapping、type。通过它们,可以让Ext.data.Reader从一个数据对象中获取各字段的值。每个字段定义对象都可能包含如下属性:

         name : String
         在记录中标志一个字段的名字。它通常用于引用指定字段,例如,在定义Ext.grid.ColumnModel的dataIndex属性时,要传过去的。
         
         mapping : String
         当在Ext.data.Reader中创建记录时,如何将json对象中指定属性值映射到此字段。

         type : String
         字段的类型,可能值为:
           auto(默认值,没有任何转化)、string、int、float、boolean、date
      sortType : Mixed
         Ext.data.SortTypes中的一个成员。

         sortDir : String
         排序方式,"ASC"或者"DESC"。

         convert : Function
         如果要对这个字段的值进行一些物殊处理,这时需要一个能定制的回调,用它来手工处理值。它的参数如下:
            v : Mixed
            通过mapping映射找到的值。已从json中取出来的。
            rec : Mixed
            在json中的,对应于此记录的json对象。

         dateFormat : String
         用于Date.parseDate函数的格式化字符串。

         defaultValue : Mixed
         当字段值在原数据中不存在时所取的默认值,默认为空字符串。

    用法:

    var TopicRecord = Ext.data.Record.create([
    {name: 'title', mapping: 'topic_title'},
    {name: 'author', mapping: 'username'},
    {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
    {name: 'lastPost', mapping: 'post_time', type: 'date'},
    {name: 'lastPoster', mapping: 'user2'},
    {name: 'excerpt', mapping: 'post_text'}
    ]);

    var myNewRecord = new TopicRecord({
    title: 'Do my job please',
    author: 'noobie',
    totalPosts: 1,
    lastPost: new Date(),
    lastPoster: 'Animal',
    excerpt: 'No way dude!'
    });
    myStore.add(myNewRecord);

    构造函数已讲,下面依代码顺序讲解了。

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

  • 相关阅读:
    网页支付宝接口使用
    @Valid注解的使用springmvc pojo校验
    Git
    面试宝典
    Navicat 破解版(操作非常简单)
    JAVA中List,Map,Set接口的区别
    java 枚举示例
    springcloud和springboot是什么关系?
    java面试经常涉及到的
    asp.net 报错 SAP 报错 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)
  • 原文地址:https://www.cnblogs.com/sharpest/p/7630388.html
Copyright © 2011-2022 走看看