Extjs 数据代理

ExtJs数据代理我们介绍常用的四种,但会着重介绍ajax代理,因为日常开发中,这个最为常用

Ext.data.proxy.Ajax

AjaxProxy(Ajax数据代理类)是你的应用程序中使用最广泛的获取数据的方式. 它使用AJAX请求来从服务器获取数据, 然后通常将它们放入 Store中. 让我们来看一个典型的配置. 这里我们为一个Store设置一个AjaxProxy代理. 首先我们准备好一个 Model:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Ext.define( 'User' , {
     extend: 'Ext.data.Model' ,
     fields: [ 'id' , 'name' , 'email' ]
});
 
//一个包含AjaxProxy代理的Store, 使用参数方式绑定.
var store = Ext.create( 'Ext.data.Store' , {
     model: 'User' ,
     proxy: {
         type: 'ajax' ,
         url : 'users.json'
     }
});
store.load();
store.each(function(record){
     console.info(record.get( 'name' ));
});

我们的例子将会把user数据加载到Store中, 首先我们定义一个Model, Model包含的字段(fields)即为从服务器返回 数据的相应字段. 接下来我们定义一个Store, 它包含了一个proxy配置项. 此配置项将会自动转换为一个 Ext.data.proxy.Ajax类的实例, 此实例包含了我们定义的url参数. 这等效于下面这段代码

?
1
2
3
4
5
new Ext.data.proxy.Ajax({
     url: 'users.json' ,
     model: 'User' ,
     reader: 'json'
});


这里出现了两个额外的参数 - model和reader. 这些参数在通过Store来创建proxy实例时是默认指定的 - Store中已经定义了 Model,并且Proxy的默认Reader为JsonReader.

最后我们调用store.load(), 触发执行AjaxProxy的action, 向配置的url发送请求(本示例为'users.json'). 由于我们执行的是数据读取, 所以讲发送一个GET方式的请求.(请求方式的定义参见actionMethods - 默认所有读数据请求(read)的方式为GET, 而所有写请求(create、update、destroy)的方式为POST)

配置项

?
1
2
3
4
5
6
actionMethods: {
     create : 'POST' ,
     read   : 'GET' ,
     update : 'POST' ,
     destroy: 'POST'
}

限制

AjaxProxy无法跨域获取数据. 例如你的程序地址为http://domainA.com, 那么你就无法从http://domainB.com获取数据. 这是因为浏览器都有 一个内置的安全机制来阻止AJAX的跨域请求.

如果你需求从其他域名地址获取数据, 并且你无法从服务器端设置代理(某些运行在你自己服务器端的程序, 用来将请求转发给http://domainB.com, 但客户端看来数据还是来自http://domainA.com), 你可以使用Ext.data.proxy.JsonP代理和JSON-P技术, 这样只要http://domainB.com 上的服务器支持JSON-P响应, 就能够解决你的跨域请求问题. 详情参见JsonPProxy的介绍文档.

配置Reader和Writer

AjaxProxy可以配置任意类型的Reader来解读服务器端的响应. 如果不显式指定Reader, 将默认使用 JsonReader. 可以使用简单属性对象的方式来配置Reader, 代理将自动将其转换为Reader类的实例:

?
1
2
3
4
5
6
7
8
9
var proxy = new Ext.data.proxy.Ajax({
     model: 'User' ,
     reader: {
         type: 'xml' ,
         root: 'users'
     }
});
 
proxy.getReader(); //返回一个XmlReader的实例.

生成Url

AjaxProxy会自动将排序,过滤,翻页和分组参数添加到生成的url中. 可以使用下面这些属性来配置这些参数:

  • pageParam - 控制如何向服务器发送页数(同样参见startParam和limitParam)
  • sortParam - 控制如何向服务器发送排序信息
  • groupParam - 控制如何向服务器发送分组信息
  • filterParam - 控制如何向服务器发送过滤信息

    每个AjaxProxy发出的请求对象由一个Operation对象来描述. 为了说明我们是如何生成自定义url的, 让我们 看看下面这个Operation:

    ?
    1
    2
    3
    4
    var operation = new Ext.data.Operation({
         action: 'read' ,
         page  : 2
    });

    然后我们用此Operation来发布请求, 通过调用read:

    ?
    1
    2
    3
    4
    5
    var proxy = new Ext.data.proxy.Ajax({
         url: '/users'
    });
     
    proxy.read(operation); //GET /users?page=2

    很简单吧 - Proxy代理类只需要复制Operation中的page值即可. 我们还能自定义如何向服务器发送page数据:

    ?
    1
    2
    3
    4
    5
    6
    var proxy = new Ext.data.proxy.Ajax({
         url: '/users' ,
         pageParam: 'pageNumber' , //默认page
    });
     
    proxy.read(operation); //GET /users?pageNumber=2

    还有另一个方案, 可以配置Operation来发送start和limit参数代替page:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var operation = new Ext.data.Operation({
         action: 'read' ,
         start : 50 ,
         limit : 25
    });
     
    var proxy = new Ext.data.proxy.Ajax({
         url: '/users'
    });
     
    proxy.read(operation); //GET /users?start=50&limit;=25
    同样地我们可以自定义startParam limitParam

    ?
    1
    2
    3
    4
    5
    6
    7
    var proxy = new Ext.data.proxy.Ajax({
         url: '/users' ,
         startParam: 'startIndex' , //默认start
         limitParam: 'pageSize' //默认limit
    });
     
    proxy.read(operation); //GET /users?startIndex=50&pageSize;=25
    AjaxProxy还会向服务器发送排序和过滤信息. 让我们来看看如何使用Operation来表示:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var operation = new Ext.data.Operation({
         action: 'read' ,
         sorters: [
             new Ext.util.Sorter({
                 property : 'name' ,
                 direction: 'ASC'
             }),
             new Ext.util.Sorter({
                 property : 'age' ,
                 direction: 'DESC'
             })
         ],
         filters: [
             new Ext.util.Filter({
                 property: 'eyeColor' ,
                 value   : 'brown'
             })
         ]
    });
    当使用一个包含sorters和filters参数的Store来加载数据时, 就会在内部生成上面这样的对象. 默认情况下, AjaxProxy 会对sorters和filters进行JSON转换, 从而得到如下结果(注意url发送前会被加密, 这里为便于阅读使用未加密的串):

    ?
    1
    2
    3
    4
    5
    var proxy = new Ext.data.proxy.Ajax({
         url: '/users'
    });
     
    proxy.read(operation); //GET /users?sort=[{"property":"name","direction":"ASC"},{"property":"age","direction":"DESC"}]&filter;=[{"property":"eyeColor","value":"brown"}]
    同样地我们能够自定义这些参数项. 假设我们的服务器读取排序信息的格式是"sortBy=name#ASC,age#DESC". 我们可以像这样配置AjaxProxy来提供这种格式:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    var proxy = new Ext.data.proxy.Ajax({
         url: '/users' ,
         sortParam: 'sortBy' ,
         filterParam: 'filterBy' ,
     
         //我们自定义实现排序信息转码方法 - 将sorters转换为"name#ASC,age#DESC"
         encodeSorters: function(sorters) {
             var length   = sorters.length,
                 sortStrs = [],
                 sorter, i;
     
             for (i = 0 ; i < length; i++) {
                 sorter = sorters[i];
     
                 sortStrs[i] = sorter.property + '#' + sorter.direction
             }
     
             return sortStrs.join( "," );
         }
    });
     
    proxy.read(operation); //GET /users?sortBy=name#ASC,age#DESC&filterBy;=[{"property":"eyeColor","value":"brown"}]
    同样我们还能够通过自定义实现encodeFilters方法来对filters信息进行转码


    Ext.data.proxy.JsonP

    JsonP代理用在当你想从你自己的应用服务器以外的域名加载数据时(跨域调用). 比如你的应用运行在http://domainA.com上, 那么就无法通过 Ajax从http://domainB.com加载数据, 因为浏览器不允许跨域的ajax请求.

    而通过JsonP代理我们可以摆脱这个限制. 每当进行AJAX请求时, JsonP代理就在DOM中注入一个<script>标签. 比如我们想从http://domainB.com/users 这个url下加载数据, 那么就会注入一个如下的script标签:

    在我们注入了上面这个标签后, 浏览器就会向这个url发送一个请求. 通过url中的callback, 我们通知domainB的服务器: 当结果返回时请调用 此回调函数并传入返回的数据. 只要服务器将响应结果组成如下格式, 调用就成功了:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Ext.regModel( "User" ,{
         fields:[
             {name: 'name' ,type: 'string' }
         ],
         proxy:{
             type: 'jsonp' , //跨域交互的代理
             url: 'http://www.uspcat.com/extjs/person.php'
         }
    });
     
    var person = Ext.ModelManager.getModel( 'User' );
    person.load( 1 ,{
         scope: this ,
         success:function(model){
             alert(model.get( 'name' ));
         }
    });



    Ext.data.proxy.LocalStorage

    LocalStorageProxy使用最新的HTML5本地数据库API, 将Model数据保存在本地客户端. HTML5本地数据库是一个 键值对存储(例如 不能存储像JSON这样的复杂对象), 因此LocalStorageProxy在保存和读取数据时, 自动进行序列化和反序列化.

    本地数据库在保存用户个人信息时非常有用, 从而不再需要在服务端建立数据结构.

    ?
    1
    2
    3
    4
    5
    6
    7
    Ext.define( 'User' , {
         fields: [ 'id' , 'name' ],
         extend: 'Ext.data.Model' ,
         proxy: {
             type: 'localstorage'
         }
    });

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var store = new Ext.data.Store({
         model: 'User'
    });
    store.add({name: 'somnus' });
    // 保存数据
    store.sync();
    // 读取数据
    store.load();
    store.each(function(record){
         console.info(record.get( 'name' ));
    });



    Ext.data.proxy.Memory

    内存代理. 此代理使用简单的本地变量进行数据的存储/读取, 所以其内容将在每次页面刷新时被清除.

    通常此代理并不直接使用, 而是作为Store的辅助服务对象, 为其在加载数据时提供reader对象. 例如, 假设我们有一个 User Model和Store, 以及一些我们想要加载的内部数据, 但是这些数据的格式并不是很合适: 这时我们就可以用一个带有JsonReader的MemoryProxy 来为Store读取这些数据:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    //我们将在store中使用的model对象
    Ext.define( 'User' , {
         extend: 'Ext.data.Model' ,
         fields: [
             {name: 'id' ,    type: 'int' },
             {name: 'name' ,  type: 'string' },
             {name: 'phone' , type: 'string' , mapping: 'phoneNumber' }
         ]
    });
     
    //数据字段不是按照model中定义排列的 - 字段'phone'在此称为'phoneNumber'
    var data = {
         users: [
             {
                 id: 1 ,
                 name: 'Ed Spencer' ,
                 phoneNumber: '555 1234'
             },
             {
                 id: 2 ,
                 name: 'Abe Elias' ,
                 phoneNumber: '666 1234'
             }
         ]
    };
     
    //请注意我们是如何通过设置reader的'root'来满足上面的数据结构的.
    var store = Ext.create( 'Ext.data.Store' , {
         autoLoad: true ,
         model: 'User' ,
         data : data,
         proxy: {
             type: 'memory' ,
             reader: {
                 type: 'json' ,
                 root: 'users'
             }
         }
    });

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    var memoryProxy = Ext.create( "Ext.data.proxy.Memory" ,{
         data:data,
         model: 'User'
    })
         
    data.push({name: 'sunday' ,age: 1 });
         
    memoryProxy.update(
         new Ext.data.Operation(
         {
             action: 'update' ,
             data:data
         }),
         function(result){},
         this
    );
         
    memoryProxy.read(
         new Ext.data.Operation(),
         function(result){
             var datas = result.resultSet.records;
             Ext.each(datas,function(model){
                 console.info(model.get( 'name' ));
             });
             var totalRecords = result.resultSet.total;
             alert( '读取内存数据,记录总是:' + totalRecords);
         }
    );
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值