日期:2014-05-16  浏览次数:20310 次

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