?有了上一篇中所讲内容,一般情况下就可以应付了,不过,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源代码分析完毕,呵呵,因为这个类代码量较少,故讲得详细。
详细解决方案
extJs 2.1学习札记(Ext.data.JsonReader篇二)
热度:148 发布时间:2012-11-22 00:16:41.0
相关解决方案
- Extjs grid 失去选中行的列数据
- extjs 后台有数据,但是返回到页面为空,jsonStore加载错误,这是咋回事
- ENCTYPE="multipart/form-data"文件下传有关问题
- enctype="multipart/form-data"的页面中,获取普通表单中文值,
- Spring Data 的有关问题
- S2SH、EXTJS、JSON调整后,EXTJS接收不到Struts2的Action传回的值,无语
- extjs 简单有关问题
- extjs+struts2解决办法
- 在jsp页面下导入.xls文件,报错:Posted content type isn't multipart/form-data
- ExtJs 处理 datetime 有关问题
- 【EXTJS】iframe里嵌套ext.window,怎样使ext.window弹出到iframe外,该怎么解决
- Tomcat + extjs 入门有关问题
- extjs ColumnModel 怎么实现表格中的数据小数点对齐
- 关于enctype="multipart/form-data"及过滤器的怪异有关问题~
- spring data jpa查询有关问题
- Extjs 变量前的一个加号代表什么意思?解决方法
- extjs grid 怎么实现 行选中变色
- ExtJs 提交表单的小疑点
- 错误详细信息: System.Data.OleDb.OleDbException: 表 'table_user' 已存在
- 错误详细信息: System.Data.OleDb.OleDbException: 表 'table_user' 已存在
- var das = eval("(" + data + ")"); 提示语法异常求解
- 晕!装.NEt Framework v1.1竟然找不到System.Data.OracleClient
- 未能加载资料或程序集“System.Data.SQLite”或它的一个依赖。试图加载格式不正确的程序
- c#中,运作程序时,提示mysql.data load failed
- 用户代码未处理 System.Data.SqlClient.SqlException 的有关问题,求教育?
- “System.Data.dll”类型的错误 高手来
- System.Data.SqlClient.SqlError: 备份集中的数据库备份与现有的 'Xblog_Data' 数据库不同,该怎么解决
- 关于.net中使用system.data.sqlite.dll,一直不太明白是如何实现的
- js转json,eval('(' + data + ')')事先和之后的数据不一致~
- MVC 客户端印证信息的 data-val-number