首页 > 代码库 > extjs proxy
extjs proxy
代理(proxy)是用来加载和存取Model 数据的。在开发过程中,我们一般不会直接操作代理,它会很好的配合Store 完成工作,所以在本节内容中,我们主要讲解各种proxy的用法。
代理(proxy)分为两大类:客户端代理和服务器端代理。客户端代理主要完成与浏览器本地存取数据相关的工作,服务器端代理则是通过发送请求,从服务器端获取数据。根据各自获取数据的方式,客户端代理和服务器端代理又可以分为一下几种:
客户端代理:
- LocalStorageProxy:将数据存储在localStorage中,此种方式可以持久的将数据存储在客户端。
- SessionStorageProxy:将数据存储在sessionStorage中,此种方式只在当前会话中生效,当关闭浏览器以后,数据也会随之丢失。
- MemoryProxy:将数据存储在内存中,此种方式只在当前页面有效,且如果刷新页面,数据将丢失。
服务器端代理:
- Ajax:在当前域中发送请求
- JsonP:跨域的请求
- Rest:与服务器进行RESTful(GET/PUT/POST/DELETE)交互
- Direct:使用 Ext.direct.Manager 发送请求
LocalStorageProxy
要使用代理,我们首先要有一个数据模型类,我们定义一个简单的Person类:
Ext.define(‘Person‘, { extend: ‘Ext.data.Model‘, fields: [‘name‘, ‘age‘] });
有了Model,我们还需要一个Store。我们可以把 Store 理解为数据仓库,它对应数据库中的表,而Store 包含的 Record 则是数据表中的每一行记录。我们同样简单的创建一个Store对象:
var personStore = Ext.create("Ext.data.Store", { model: ‘Person‘ });
接下来就到我们代理出场的时候了。我们需要创建一个LocalStorageProxy:
var personProxy = new Ext.data.proxy.LocalStorage({ id: ‘Person_LocalStorage‘, model: ‘Person‘ });
有了代理,我们需要将代理和Store联系起来:
personStore.setProxy(personProxy);
其实,在我们实际应用中,可以在Model 或 Store 中直接使用proxy 选项,我们在后面的示例中将会看到具体的用法。
有了Store 和 Proxy,我们先保存一条数据到LocalStorage中:
personStore.add({ name: ‘www.qeefee.com‘, age: 1 }); personStore.add({ name: ‘qf‘, age: 26 }); personStore.add({ name: ‘qifei‘, age: 26 }); personStore.sync();
要查看保存的数据,我们需要先将数据从LocalStorage中加载到Store中,然后对Store 进行遍历:
personStore.load(); var msg = []; personStore.each(function (person) { msg.push(person.get(‘name‘) + ‘ ‘ + person.get(‘age‘)); }); Ext.MessageBox.alert(‘提示‘, msg.join(‘<br />‘));
我们可以看到这样的提示:
使用load方法会将所有的数据都加载到Store中,如果我们需要进行查询指定的数据,就要用到filter方法了。
personStore.filter("name", /\.com$/);
我们使用这个filter过滤以.com结尾的name字段,最后得到的结果:
另外,我们还可以使用多个过滤条件:
personStore.filter([ { property: "name", value: /\.com$/ }, { filterFn: function (item) { return item.get("age") > 10; } } ]);
这两个过滤条件是“and”的关系,所以我们目前没有符合的数据。
注意第二个过滤条件,它传入的是一个方法,这种方式可以方便我们自定义过滤条件,如果我们的业务需求比较复杂,我们可以使用过滤方法替代这些过滤条件:
personStore.filter(function (item) { return item.get("age") > 10 && item.get(‘name‘).length > 3; });
这里我们过滤age大于10,且名字长度大于3的数据,得到的结果如下:
更新操作:
//得到第一个person对象 var person = personStore.first(); //修改名字字段 person.set(‘name‘, ‘qeefee.com‘); //保存到本地 personStore.sync();
删除操作:
//得到第一个person对象 var person = personStore.first(); //移除 personStore.remove(person); //保存 personStore.sync();
SessionStorageProxy
SessionStorageProxy 的用法与LocalStorageProxy 的用法基本一致,我们这次在Model中添加proxy 的配置项:
//定义数据模型 Ext.define(‘Person‘, { extend: ‘Ext.data.Model‘, fields: [‘name‘, ‘age‘], proxy: { type: ‘sessionstorage‘, id: ‘myProxyKey‘ } });
在Model中加入代理配置以后,我们就不需要单独的定义代理对象了,可以直接使用Store来对其进行操作:
//定义Store var personStore = Ext.create("Ext.data.Store", { model: ‘Person‘ }); //添加数据 personStore.add({ name: ‘www.qeefee.com‘, age: 1 }); personStore.add({ name: ‘qf‘, age: 26 }); personStore.add({ name: ‘qifei‘, age: 26 }); personStore.sync(); //读取数据 personStore.load(); var msg = []; personStore.each(function (person) { msg.push(person.get(‘name‘) + ‘ ‘ + person.get(‘age‘)); }); Ext.MessageBox.alert(‘提示‘, msg.join(‘<br />‘));
MemoryProxy
MemoryProxy 是将数据存储在内存中的,它只在当前页生效,如果关闭或刷新页面,所有数据都将丢失。在使用MemoryProxy 的时候,我们需要为Store指定一个数据集(类似于缓存),store 将通过代理对这个数据集进行操作:
//定义数据模型 Ext.define(‘Person‘, { extend: ‘Ext.data.Model‘, fields: [‘name‘, ‘age‘] }); var
data = http://www.mamicode.com/{ Users: [ { name: ‘www.qeefee.com‘, age: 1 }, { name: ‘qeefee‘
, age: 1 } ] } //定义Store var personStore = Ext.create("Ext.data.Store", { model: ‘Person‘, data: data.Users, proxy: { type: ‘memory‘ } });
在代码中高亮显示的部分,就是为store设置的缓存。当personStore 定义的时候,它就会自动的将数据加载到Store中,所以在我们访问数据的时候不需要再调用load方法了:
//读取数据 var msg = []; personStore.each(function (person) { msg.push(person.get(‘name‘) + ‘ ‘ + person.get(‘age‘)); }); Ext.MessageBox.alert(‘提示‘, msg.join(‘<br />‘));
和上两个的操作基本一致,我们可以通过下面的代码添加一行新数据:
personStore.add({ name: ‘qifei‘, age: 26 }); personStore.sync();
本节内容主要介绍了浏览器端代理的用法,在下节内容中,我将介绍如何使用服务器端代理进行数据的操作。
如果认为此文对您有帮助,别忘了支持一下哦!
在上一节我们介绍了客户端的几种代理,本节的主要内容是介绍如何使用服务器端代理,将重点介绍AjaxProxy,这是我们最常用的代理方式。
Ajax
web应用程序开发过程中,与服务器端交互的技术最常用的就是Ajax了。Ajax 是使用Javascript创建一个HttpRequest,采用异步的方式从服务器获取数据。我们先看一个简单的示例:
Ext.onReady(function () { Ext.define(‘Person‘, { extend: ‘Ext.data.Model‘, fields: [‘name‘, ‘age‘] }); var store = Ext.create(‘Ext.data.Store‘, { model: ‘Person‘, proxy: { type: ‘ajax‘, url: rootUrl + ‘sample/getjson‘, reader: { type: ‘json‘, root: ‘users‘ } } }); store.load(); var msg = []; store.each(function (person) { msg.push(person.get(‘name‘) + ‘ ‘ + person.get(‘age‘)); }); Ext.MessageBox.alert(‘提示‘, msg.join(‘<br />‘)); });
在这段代码中,首先定义了Model类Person,然后创建了Person类的数据仓库 store,store 使用了ajax代理,通过url向服务器请求数据,ajax代理的reader 配置项是告诉程序以何种方式读取请求到的数据。
我们从服务器返回的JSON字符串如下:
{users:[{name:‘www.qeefee.com‘, age:1}, {name:‘Tom‘, age:26}]}
大家先猜想一下运行结果?按照上一节的逻辑,此处应该弹出一个对话框,上面将内容内容显示出来,但真正运行的时候得到的却是空的内容,截图如下:
难道我们没有请求到数据?当然不是,如果你打开网络跟踪,会发现程序已经将成功得到了这段JSON字符串。那是为什么仍然是空呢?
原因是当我们调用load()方法的时候,我们告诉store去请求数据吧,然后store就使用ajax的方式请求url,注意,ajax 是异步的,所以当我们调用load()方法以后,马上执行输出的时候,store仍然是空的,可能它还在等待服务器响应数据。
所以,在我们使用ajax方式加载数据的时候,就需要为load() 方法添加一个callback 方法,当数据加载完成以后,再callback方法中进行数据输出,修改load方法的调用:
store.load({ callback: function (records, operation, success) { if (success) { var msg = []; store.each(function (person) { msg.push(person.get(‘name‘) + ‘ ‘ + person.get(‘age‘)); }); Ext.MessageBox.alert(‘提示‘, msg.join(‘<br />‘)); } } });
刷新页面,这次才是我们想要的结果:
ajax 带参数的请求
我们打开网络跟踪,刷新页面,跟踪我们所有的网络请求:
找到getjson的请求,点击查看明细:
在这个URL中可以看到,ExtJS 其实已经为我们添加了一些参数,包括 page、start和limit。这些参数是从哪儿来的呢?
在使用ajax进行请求的时候,ajax代理会调用自身的read方法,该方法的第一个参数是Ext.data.Operation 类型,它用来配置我们如何进行请求。我们在load 方法中可以通过配置项传递一些参数,load在调用read方法时将这些参数传递过去,read则会根据这些参数生成Ext.data.Operation 的一个实例。所以,我们可以这样来传递参数:
store.load({ page: 2, limit: 10, params: { name:‘QF‘ }, callback: function (records, operation, success) { if (success) { var msg = []; store.each(function (person) { msg.push(person.get(‘name‘) + ‘ ‘ + person.get(‘age‘)); }); Ext.MessageBox.alert(‘提示‘, msg.join(‘<br />‘)); } } });
我们再次跟踪请求,传递的地址变成了 /SampleExtJS/sample/getjson?_dc=1374141754304&name=QF&page=2&start=25&limit=10
通过传递这些参数,我们可以完成分页、查询等操作。
JsonP
在Javascript 中,由于跨域操作存在很严重的安全隐患,所以浏览器不允许我们直接使用ajax 进行跨域请求。当用到跨域请求的时候,我们可以使用请求javascript 资源的形式,将要请求的Json数据作为Javascript 代码加载到浏览器中(浏览器不会阻止跨域的资源请求,资源包括Javascript、css、图片等)。具体做法:使用 Javascript 动态添加一个script 标签,将要请求的资源URL 作为src的属性传递过去(请求url中通常包含一个callback方法名的参数),服务器端对请求的数据进行包装,然后返回给客户端。
在ExtJS 中我们可以轻松的使用JsonP代理进行跨域的数据请求:
//创建Store var store = Ext.create(‘Ext.data.Store‘, { model: ‘Person‘, proxy: { type: ‘jsonp‘, url: ‘http://www.abc.com/sampleextjs/sample/getjsonp‘, reader: { type: ‘json‘, root:‘users‘ } } });
在测试中,我们的本机名是localhost,所以对域名abc.com进行数据请求是跨域的操作(我们在第二节 bootstrap.js的工作方式 中已经对本机的hosts文件进行了修改,将abc.com也指向本地)。
然后添加服务器段代码,在SampleController 中添加getJsonP方法:
public string GetJsonP() { string callback = Request["callback"]; if (string.IsNullOrEmpty(callback)) callback = "callback"; Response.ContentType = "text/javascript"; return callback + "({users:[{name:‘www.qeefee.com‘, age:1}, {name:‘QF‘, age:26}]})"; }
这段代码中,我们首先得到请求中的callback参数,如果没有则默认为“callback”字符串。然后将拼接好的JSON字符串作为参数传递给callback方法,我们在这里返回的字符串要遵循Javascript 语法。
编译项目,然后刷新页面,打开开发人员工具,跟踪网络请求,你会发现在进行网络请求的时候,ExtJS 会自动为请求地址添加回调方法,url中包含参数:callback=Ext.data.JsonP.callback1,根据传入的callback参数,我们服务器返回的字符串为:
Ext.data.JsonP.callback1({ users: [{ name: ‘www.qeefee.com‘, age: 1 }, { name: ‘QF‘, age: 26 }] })
这段代码可以被当做Javascript代码在加载完成后执行。我们的运行结果如图:
ExtJS 提供的这种方式大大简化了我们客户端的处理代码,方便我们进行JsonP跨域请求。
JsonP代理的其它操作跟Ajax代理基本一直,不再过多介绍。接下来看一下Rest代理。
Rest
Rest 指的是什么呢?根据我个人的理解,我觉得Rest像是一种开发规范,由于Http请求是无状态的,所以在对网络资源进行请求的时候,我们通常会将状态(要执行的操作:增删改查等,以及要操作的数据)作为参数传递给服务器,而Rest 则规定,HttpMethod 的GET、POST、PUT、DELETE分别对应不同的操作(Get 对应查找、PUT对应更新、POST对应新增、DELETE对应删除)。关于更完整的Rest,请参照《深入浅出REST》。
在ASP.NET MVC 中,我们可以使用Web API 轻松的实现RESTful应用程序。
我们首先在服务器段用C#代码定义一个Model:
public class User { public string name { get; set; } public int age { get; set; } }
然后创建针对User类操作的UserController,它需要继承自ApiController,代码如下:
public class UserController : ApiController { public static List<User> UserList = null; static UserController() { if (UserList == null) { UserList = new List<User>(); UserList.Add(new User() { name = "www.qeefee.com", age = 1 }); UserList.Add(new User() { name = "QF", age = 26 }); } } // GET api/<controller> public List<User> Get() { return UserList; } // GET api/<controller>/5 public List<User> Get(string name) { List<User> result = new List<User>(); foreach (User item in UserList) { if (item.name == name) result.Add(item); } return result; } // POST api/<controller> public void Post([FromBody]User user) { UserList.Add(user); } // PUT api/<controller>/5 public void Put([FromBody]User user) { UserList.Add(user); } // DELETE api/<controller>/5 public void Delete(string name) { for (int i = UserList.Count - 1; i >= 0; i--) { User user = UserList[i]; if (user.name == name) { UserList.RemoveAt(i); } } } }
由于API针对不同的HttpMethod 选择不同的操作,所以当我们直接使用浏览器请求API的时候,我们将得到第一个Get方法的返回结果:
由于我们没有指明返回的数据格式,所以默认为我们将对象转换为Xml。我们在ExtJS中使用Rest代理:
//创建Store var store = Ext.create(‘Ext.data.Store‘, { model: ‘Person‘, proxy: { type: ‘rest‘, url: rootUrl + ‘api/user/‘, reader: { type: ‘json‘ } } });
然后使用load方法加载数据:
store.load({ callback: function (records, operation, success) { var msg = []; store.each(function (item) { msg.push(item.get(‘name‘) + ‘ ‘ + item.get(‘age‘)); }); Ext.MessageBox.alert(‘提示‘, msg.join(‘<br />‘)); } });
此时跟踪Network请求:
红框中的是我们请求的URL和得到的数据的预览。我们程序完成解析后会弹出提示:
此时我们可以对store执行一些CRUD操作,跟踪一下网络请求和服务器段代码,查看一下Rest代理是如何工作的。
Direct
Direct 代理使用Ext.Direct 向服务器发送数据。
Ext.Direct 技术的好处是,允许你像调用Javascript 方法一样调用服务器端代码。我们将在后面的章节中详细的介绍 Ext.Direct。当我们定义好Ext.Direct 以后,才能够使用Direct代理来请求数据。
例如我们在API中看到的代码:
Ext.define(‘User‘, { extend: ‘Ext.data.Model‘, fields: [‘firstName‘, ‘lastName‘], proxy: { type: ‘direct‘, directFn: MyApp.getUsers, paramOrder: ‘id‘ // Tells the proxy to pass the id as the first parameter to the remoting method. } }); User.load(1);
本节内容介绍了服务器端代理的使用方法,这些基础性的内容比较枯燥,但却是学习ExtJS 复杂控件的基础,在这些内容的基础上,我们才能够更加轻松的学习Grid、Tree 等复杂控件。
如果认为此文对您有帮助,别忘了支持一下哦!
extjs proxy