ExtJS笔记--Ext.data详解

Ext.data

Ext.data在命名空间中定义了一系列store、reader和proxy。Grid和ComboxBox都是以Ext.data为媒介获取数据的,它包含异步加载、类型转换、分页等功能。Ext.data默认支持Array、JSON、XML等数据格式,可以通过Memory、HTTP、ScriptTag等方式获得这些格式的数据。如果要实现新的协议和新的数据结构,只需要扩展reader和proxy即可。DWRProxy就实现了自身的proxy和reader,让EXT可以直接从DWR获得数据。

Ext.data最主要的功能是获取和组织数据结构,并和特定控件联系起来,于是Ext.data成了数据的来源,而控件负责显示数据;;;

以下为Ext.data命名空间中的在个常用类:

1、DataProxy

2、DataReader

3、Store

关于数据的显示,一般要经历三个流程:DataProxy-->DataReader-->Store

一、Ext.data.Connection

Ext.data.Connection是对Ext.lib.Ajax的封装,它提供了配置使用Ajax的通用方式,它在内部通过Ext.lib.Ajax实现与后台的异步调用。与底层的Ext.lib.Ajax相比,Ext.data. Connection提供了更简洁的配置方式,使用起来更方便。

  Ext.data.Connection主要用于在Ext.data.HttpProxy和Ext.data.ScriptTagProxy中执行与后台交互的任务,它会从指定的URL获得数据,并把后台返回的数据交给HttpProxy或ScriptTagProxy处理,Ext.data.Connection的使用方式如代码清单10-1所示。

  代码清单10-1 使用Ext.data.Connection

  var conn = new Ext.data.Connection({

autoAbort: false,

defaultHeaders: {

referer: 'http://localhost:8080/'

},

disableCaching : false,

extraParams : {

name: 'name'

},

method : 'GET',

timeout : 300,

url : '01-01.txt'

});

  在使用Ext.data.Connection之前,都要像上面这样创建一个新的Ext.Connection实例。我们可以在构造方法里配置对应的参数,比如autoAbort表示链接是否会自动断开、default- Headers参数表示请求的默认首部信息、disableCaching参数表示请求是否会禁用缓存、extraParams参数代表请求的额外参数、method参数表示请求方法、timeout参数表示连接的超时时间、url参数表示请求访问的网址等。

  在创建了conn之后,可以调用request()函数发送请求,处理返回的结果,如下面的代码所示。

  conn.request({

   success: function(response) {

   Ext.Msg.alert('info', response.responseText);

   },

  failure: function() {

  Ext.Msg.alert('warn', 'failure');

  }

  });

  Request()函数中可以设置success和failure两个回调函数,分别在请求成功和请求失败时调用。请求成功时,success函数的参数就是后台返回的信息。

  我们再来看一下request函数中的其他参数。

  q url:String:请求url。

  q params:Object/String/Function:请求传递的参数。

  q method:String:请求方法,通常为GET或POST。

  q callback:Function:请求完成后的回调函数,无论是成功还是失败,都会执行。

  q success:Function:请求成功时的回调函数。

  q failure:Function:请求失败时的回调函数

  q scope:Object:回调函数的作用域。

  q form:Object/String:绑定的form表单。

  q isUpload:Boolean:是否执行文件上传。

  q headers:Object:请求首部信息。

  q xmlData:Object:XML文档对象,可以通过URL附加参数的方式发起请求。

  q disableCaching:Boolean:是否禁用缓存,默认为禁用。

  Ext.data.Connection还提供了abort([Number transactionId])函数,当同时有多个请求发生时,根据指定的事务id放弃其中的某一个请求。如果不指定事务id,就会放弃最后一个请求。isLoading([Number transactionId])函数的用法与abort()类似,可以根据事务id判断对应的请求是否完成。如果未指定事务id,就判断最后一个请求是否完成。

二、Ext.data.Record

Ext.data.Record就是一个设定了内部数据类型的对象,它是Ext.data.Store的最基本组成部分。如果把Ext.data.Store看作是一张二维表,那么它的每一行就对应一个Ext.data. Record实例。

  Ext.data.Record的主要功能是保存数据,并且在内部数据发生改变时记录修改的状态,它还可以保留修改之前的原始值。

  我们使用Ext.data.Record时通常都是由create()函数开始,首先用create()函数创建一个自定义的Record类型,如下面的代码所示。

  var PersonRecord = Ext.data.Record.create([

   {name: 'name', type: 'string'},

   {name: 'sex', type: 'int'}

  ]);

  PersonRecord就是我们定义的新类型,包含字符串类型的name和整数类型的sex两个属性,然后我们使用new关键字创建PersonRecord的实例,如下面的代码所示。

  var boy = new PersonRecord({

   name: 'boy',

   sex: 0

  });

  创建对象时,可以直接通过构造方法为对象赋予初始值,将'boy'赋值给name,0赋值给sex。

  现在,我们得到了PersonRecord的实例boy,如何才能得到它的属性呢?以下三种方式都可以获得boy中name属性的数据,如下面的代码所示。

  alert(boy.data.name);

  alert(boy.data['name']);

  alert(boy.get('name'));

  这里涉及Ext.data.Record的data属性,这是定义在Ext.data.Record中的一个公共属性,用于保存当前record对象的所有数据。它是一个JSON对象,可以直接从它里面获得需要的数据。可以通过Ext.data.Record的get()函数方便地从data属性中获得指定的属性值。

  如果我们需要修改boy中的数据,请不要使用以下方式直接操作data,如下面的代码所示。

  boy.data.name = 'boy name';

  boy.data['name'] = 'boy name';

  而应该使用set()函数,如下面的代码所示。

  boy.set('name', 'body name');

  set()函数会判断属性值是否发生了改变,如果改变了,就要将当前对象的dirty属性设置为true,并将修改之前的原始值放入modified对象中,供其他函数使用。如果直接操作data中的值,record就无法记录属性数据的修改情况。

  Record的属性数据被修改后,我们可以执行如下几种操作。

  q commit()(提交):这个函数的效果是设置dirty为false,并删除modified中保存的原始数据。

  q reject()(撤销):这个函数的效果是将data中已经修改了的属性值都恢复成modified中保存的原始数据,然后设置dirty为false,并删除保存原始数据的modified对象。

  q getChanges()获得修改的部分:这个函数会把data中经过修改的属性和数据放在一个JSON对象里并返回。例如上例中,getChanges()返回的结果是{name:’body name’}。

  q 我们还可以调用isModified()判断当前record中的数据是否被修改。

  Ext.data.Record还提供了用于复制record实例的函数copy()。

  var copyBoy = boy.copy();

  这样我们就得到了boy的一个副本,它里面包含了boy的data数据,但copy()函数不会复制dirty和modified等额外的属性值。

三、DataProxy

获取想要的数据,通过他能得到来自不同地方的数据,如数组、远程服务器等,并组织成不同的格式。

Ext.data.DataProxy是获取数据的代码,数据可能来于内存,可能来自于同一域的远程服务器数据,更有可能来自于不同域的远程服务器数据。

DataProxy的代码就是一空架子。且看: 

Ext.data.DataProxy = function(){ 

    this.addEvents( 

        'beforeload', 

        'load' 

    ); 

    Ext.data.DataProxy.superclass.constructor.call(this); 

}; 

Ext.extend(Ext.data.DataProxy, Ext.util.Observable); 

就是加两事件,从Observable继承了

但在实际应用中,不会直接使用Ext.data.DataProxy类,而是使用他的子类:

1、MemoryProxy:获取来自内存的数据,可以是数组、json或者xml

2、HttpProxy:使用HTTP协议通过ajax从远程服务器获取数据的代理,需要指定url

3、ScriptTagProxy:功能和HttpProxy一样,但支持跨域获取数据。

(一)、MemoryProxy

MemoryProxy只能从JavaScript对象获得数据,可以直接把数组,或JSON和XML格式的数据交给它处理,如下面的代码所示。

var proxy = new Ext.data.MemoryProxy([

['id1','name1','descn1'],

['id2','name2','descn2']

]);

例如:定义一个用来保存城市名称的二维数组:

Var cities = [

[1,"长沙市"],

[2,"株洲市"],

[3,"湘潭市"],

[4,"邵阳市"]

];

在二维数组中,每一个城市保存了两个值:值一表示城市编号,作为实际值,值二表示城市名称,作为显示值,然后将其构建出一个MemoryProxy对象:

var proxy = new Ext.data.MemoryProxy(cities);

(二)、HttpProxy

HttpProxy使用HTTP协议,通过Ajax去后台取数据,构造它时需要设置url:'xxx.jsp'参数。这里的url可以替换成任何一个合法的网址,这样HttpProxy才知道去哪里获取数据,如下面的代码所示。

var proxy = new Ext.data.HttpProxy({url:'xxx.jsp'});  

HttpProxy用于远程代理,而且服务端返回信息时必须指定Content-Type属性为"text/xml"或"application/x-json"          

后台需要返回EXT所需要的JSON格式的数据,下面的内容就是后台使用JSP的一个范例,如下面的代码所示。

HttpProxy( Object conn ) 构造一个HttpProxy对象,参数可以是一个类似于{url: 'foo.php'}这样的json对象,也可以是一个Ext.data.Connection对象,如果参数没有指定,将使用Ext.Ajax对象将被用于发起请求

getConnection() : Connection 得到当前连接对象

load( Object params, Ext.data.DataReader reader, Function callback, Object scope, Object arg ) : void

从配置的connection对象得到record数据块,并激发callback

params:        发起http请求时所要传递到服务端的参数

DataReader:    见DataReader

callback:    回叫方法,第一个参数为接收到的信息,第二个参数为arg,第三个是成功标志

scope:        范围

arg:        这儿的参数将会传递给回叫函数callback

使用示例:

var proxy=new Ext.data.HttpProxy({url:'datasource.xml'});

    //关于reader将会在Ext.data.DataReader中讲解

    var reader = new Ext.data.XmlReader({

       totalRecords: "results", 

       record: "row",         

       id: "id"                 

    }, [

       {name: 'name', mapping: 'name'},

       {name: 'occupation'}            

    ]);

    

    //定义回叫方法

    var metadata;

    function callback(data,arg,success){

        if(success){

            metadata=data;

        }

    }

 //从connection配置的url中利用reader将返回的xml文件转为元数据,并传递给callback

     proxy.load( null,reader,callback,this);

response.setContentType("application/x-json");

Writer out = response.getWriter();

out.print("[" +

"['id1','name1','descn1']" +

"['id2','name2','descn2']" +

"]");               

(三)、ScriptTagProxy

ScriptTagProxy的用法几乎和HttpProxy一样,如下面的代码所示。

var proxy = new Ext.data.ScriptTagProxy({url:'xxx.jsp'});          

从这里也看不出来它是如何支持跨域的,我们还需要在后台进行相应的处理,如下面的代码所示

String cb = request.getParameter("callback");

response.setContentType("text/javascript");

Writer out = response.getWriter();

out.write(cb + "(");

out.print("[" +

"['id1','name1','descn1']" +

"['id2','name2','descn2']" +

"]");

out.write(");");

其中的关键就在于从请求中获得的callback参数,这个参数叫做回调函数。ScriptTag- Proxy会在当前的HTML页面里添加一个<script type="text/javascript"src="/xxx.jsp"> </script>标签,然后把后台返回的内容添加到这个标签中,这样就可以解决跨域访问数据的问题。为了让后台返回的内容可以在动态生成的标签中运行,EXT会生成一个名为callback的回调函数,并把回调函数的名称传递给后台,由后台生成callback(data)形式的响应内容,然后返回给前台自动运行。

虽然上述处理过程比较难理解,但是我们只需要了解ScriptTagProxy的用法就足够了。如果还想进一步了解ScriptTagProxy的运行过程,可以使用Firebug查看动态生成的HTML以及响应的JSON内容。

最后我们来分析一下EXT的API文档中提供的示例,这段后台代码会自动判断请求的类型,返回支持ScriptTagProxy或HttpProxy的数据,如代码清单10-2所示。

代码清单 在后台同时支持HttpProxy和ScriptTagProxy

boolean scriptTag = false;

String cb = request.getParameter("callback");

if (cb != null) {

scriptTag = true;

response.setContentType("text/javascript");

} else {

response.setContentType("application/x-json");

}

Writer out = response.getWriter();

if (scriptTag) {

out.write(cb + "(");

}

out.print(dataBlock.toJsonString());

if (scriptTag) {

out.write(");");

分享到:
评论

你可能感兴趣的:(JavaScript,数据结构,Ajax,json,ext)