西沙璞玉
          愛(ài)不容易
          posts - 0,comments - 4,trackbacks - 0

          嘿,別看關(guān)鍵就在這兒,事實(shí)上,它的代碼很少的哦。加上注釋才219行。研究研究。

            有個(gè)事要說(shuō)一下:DataProxy的子類呢,都有一個(gè)load來(lái)加載數(shù)據(jù),DataReader的子類呢,都有一個(gè)read來(lái)讀取數(shù)據(jù)。

            而Ext.data.JsonReader有兩個(gè)關(guān)鍵函數(shù):read、readRecords。好了。來(lái)研究一下。

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

            這是構(gòu)造函數(shù)。簡(jiǎn)單。meta是數(shù)據(jù)格式定義,recordType是記錄類型。其中recordType可以是一個(gè)定義記錄的數(shù)組,也可以不傳,而把記錄的各個(gè)字段的定義放到meta中的fields字段中。且看它對(duì)父類構(gòu)造函數(shù)的調(diào)用:

            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可以是記錄類型,可以是字段定義數(shù)組,還可以不傳。

            所以,構(gòu)造函數(shù)就是定義兩個(gè)屬性:meta、recordType。這兩東西后面有用。

            這個(gè)meta、recordType組成如何?這個(gè)必須說(shuō)明,不然,這個(gè)類也就沒(méi)法用了。

            meta:

            totalProperty    json數(shù)據(jù)中,保存總記錄數(shù)的屬性

            successProperty   json數(shù)據(jù)中,保存是否返回成功的屬性名

            root        json數(shù)據(jù)中,保存記錄集的屬性的屬性名

            id         json數(shù)據(jù)中,記錄中主鍵所對(duì)應(yīng)的列的屬性名

            recordType:

            這個(gè)東西,事實(shí)上要去看Ext.data.Record的create函數(shù)的文檔,我且把它翻譯一下,如下:

          create( [Array o] ) : function

          創(chuàng)建包含指定字段結(jié)構(gòu)的繼承自Ext.data.Record的類。靜態(tài)方法。

          參數(shù):
            o : Array
              一個(gè)定義記錄結(jié)構(gòu)的字段信息數(shù)組。每個(gè)數(shù)組元素包含name,其他可選的有:mapping、type。通過(guò)它們,可以讓Ext.data.Reader從一個(gè)數(shù)據(jù)對(duì)象中獲取各字段的值。每個(gè)字段定義對(duì)象都可能包含如下屬性:

               name : String
               在記錄中標(biāo)志一個(gè)字段的名字。它通常用于引用指定字段,例如,在定義Ext.grid.ColumnModel的dataIndex屬性時(shí),要傳過(guò)去的。

               
               mapping : String
               當(dāng)在Ext.data.Reader中創(chuàng)建記錄時(shí),如何將json對(duì)象中指定屬性值映射到此字段。

               type : String
               字段的類型,可能值為:
                 auto(默認(rèn)值,沒(méi)有任何轉(zhuǎn)化)、string、int、float、boolean、date
                   
                      sortType : Mixed
               Ext.data.SortTypes中的一個(gè)成員。

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

               convert : Function
               如果要對(duì)這個(gè)字段的值進(jìn)行一些物殊處理,這時(shí)需要一個(gè)能定制的回調(diào),用它來(lái)手工處理值。它的參數(shù)如下:
                  v : Mixed
                  通過(guò)mapping映射找到的值。已從json中取出來(lái)的。
                  rec : Mixed
                  在json中的,對(duì)應(yīng)于此記錄的json對(duì)象。

               dateFormat : String
               用于Date.parseDate函數(shù)的格式化字符串。

               defaultValue : Mixed
               當(dāng)字段值在原數(shù)據(jù)中不存在時(shí)所取的默認(rèn)值,默認(rèn)為空字符串。

          用法:

          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);

          不過(guò),JsonReader有一些細(xì)節(jié)問(wèn)題,還要細(xì)究。待某家一一道來(lái)。

            構(gòu)造函數(shù)已講,下面依代碼順序講解了。

              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);
              },

            這個(gè)是整個(gè)JsonReader的關(guān)鍵所在了。君可找到Ext.data.HttpProxy中的loadResponse函數(shù),里面有這么一行代碼:

            result = o.reader.read(response);

            可見(jiàn),是proxy里面調(diào)用reader.read方法才得以取出結(jié)果集的。這是要表明:read乃JsonReader三軍中軍之所在。 read又調(diào)用readRecords,read把json字符串轉(zhuǎn)化為對(duì)象然后交給readRecords。這個(gè)本無(wú)不妥,但是,asp.net中,它的結(jié)果有點(diǎn)曲折,結(jié)果是放在o.d中,而不能直接從o中取得。所以,事實(shí)上應(yīng)當(dāng)這么寫(xiě):this.readRecords(o.d)。 這就成了。繼續(xù)往下面看:

              onMetaChange : function(meta, recordType, o){

              }

            這個(gè)函數(shù)說(shuō)是要由store實(shí)現(xiàn)的,現(xiàn)在不知道它的用處。還往下看:
              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;
                  };
              }(),

            取一對(duì)象的屬性有兩種方法,前面都已提及:

            一、obj.xxxx

            二、obj[xxxx]

            這兩種都行。但是,如果傳過(guò)來(lái)一個(gè)對(duì)象,已知其對(duì)象的引用obj,但是有的只是它的屬性名的字符串,這時(shí)就可以用第二種方法取出,但是,如屬性名中含[],那么就不大方便了,又或者是屬性又帶屬性,這事也只能用第一種方法。這兩個(gè)函數(shù)正是為事而來(lái)。且看那getJsonAccessor,著實(shí)巧妙,函數(shù)返回一函數(shù),這不是巧妙之處,這個(gè)我以前就見(jiàn)識(shí)了,關(guān)鍵在于new Function("obj","return "obj."+expr) 。多么巧妙啊。此之中巧,不足以言語(yǔ)道哉。

            這下面就是真正的好戲了,看一看readRecords函數(shù)。

                  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);
                  }

            定義一個(gè)jsonData屬性以保存原始json對(duì)象。然后如果傳過(guò)的json對(duì)象中就有metaData。那么,就用它自帶的meta來(lái)取代JsonReader構(gòu)造函數(shù)中所傳入的meta。以原來(lái)自帶的為主。這個(gè)功能方檔未曾提及,但我輩不可不察也。

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

            有人不理解了,為什么非得這樣呢?這是節(jié)省帶寬啊。如果這些東西以后多說(shuō)現(xiàn)幾次,那么每個(gè)用戶都要多下載一些東西,成千上萬(wàn)人能節(jié)省多少啊。

                  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);
                      }
                  }

            因?yàn)橐鶕?jù)meta.id、meta.root。這兩值都是字符串,這就要用到前面定義的getJsonAccessor函數(shù)了。這兒正是來(lái)生成幾個(gè)取json對(duì)象中屬性的函數(shù),如:getTotal、getSuccess、getRoot、getId、ef數(shù)組,一個(gè)ef數(shù)組就解決了屬性映射的問(wèn)題,真是漂亮。

              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后面要用來(lái)循環(huán)的,而totalRecords是要返回的,而后,又求了totalRecords,這個(gè)意思是:如果結(jié)果中沒(méi)有 totalProperty這一屬性,那么就自動(dòng)求取,如果存在,則以定義的totalProperty為主,由此可見(jiàn),totalProperty是可有可無(wú)的。這個(gè)問(wèn)題文檔不曾見(jiàn)之。諸位可無(wú)憂矣。

               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++)可知,循環(huán)的時(shí)候還是用root.length的。而不是totalProperty。這個(gè)要分清,事實(shí)上,totalProperty只是直接返回罷了,未做任何改動(dòng)。里面就轉(zhuǎn)化成Record了。其中,這個(gè)ef數(shù)組用得巧妙。類型轉(zhuǎn)化用了convert。這個(gè)東西前文已講,不足道哉。

            var record = new Record(values, id);

            id=this.getId(n),可見(jiàn)啦,id并非前文所說(shuō)的主鍵,它只是一個(gè)用來(lái)做客戶端唯一編號(hào)的東西,如對(duì)此有疑,可見(jiàn)于Ext.data.Record類。

            record.json = n,json這個(gè)屬性我在Ext.data.Record類中并未曾得見(jiàn),諸君注意了,這個(gè)東西也許會(huì)有用。另外,readRecords返回的不只是一個(gè)records數(shù)組,而是一個(gè)json對(duì)象,包含success、records、totalRecords。

            至此,JsonReader源代碼分析完畢,呵呵,因?yàn)檫@個(gè)類代碼量較少,故講得詳細(xì)。

          posted on 2012-04-28 12:46 @趙 閱讀(1433) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          哥哥最近不是很忙
          主站蜘蛛池模板: 晋江市| 绩溪县| 上蔡县| 怀集县| 民勤县| 西华县| 昭觉县| 曲周县| 阿尔山市| 黔西| 石景山区| 昌宁县| 伊宁市| 正定县| 稷山县| 西盟| 林周县| 峨山| 长宁县| 那曲县| 合江县| 远安县| 太仆寺旗| 和林格尔县| 定州市| 电白县| 松阳县| 昌都县| 临沂市| 永平县| 文昌市| 交城县| 莲花县| 深水埗区| 潮州市| 雷山县| 化隆| 广灵县| 扬中市| 台州市| 长岛县|