Proxies are used by Stores to handle the loading and saving of Model data. Usually developers will not need to create or interact with proxies directly.
proxy被Store使用以实现加载和保存model数据。通常,开发者不需要直接创建代理或代理交互。
Types of Proxy 代理的类型
There are two main types of Proxy - Client and Server. The Client proxies save their data locally and include the following subclasses:
有两种主要的代理类型-客户端和服务器端。客户端代理在本地保存数据,包括以下子类:
- LocalStorageProxy - saves its data to localStorage if the browser supports it
- SessionStorageProxy - saves its data to sessionStorage if the browsers supports it
- MemoryProxy - holds data in memory only, any data is lost when the page is refreshed
The Server proxies save their data by sending requests to some remote server. These proxies include:
服务端代理通过发送请求道远程服务器来保存数据,包括:
- Ajax - sends requests to a server on the same domain
- JsonP - uses JSON-P to send requests to a server on a different domain
- Rest - uses RESTful HTTP methods (GET/PUT/POST/DELETE) to communicate with server
- Direct - uses Ext.direct.Manager to send requests
Proxies operate on the principle that all operations performed are either Create, Read, Update or Delete. These four operations are mapped to the methods create, read, update and destroy respectively. Each Proxy subclass implements these functions.
代理的基础原则--所有的操作都限于Create, Read, Update or Delete这几种。这四个操作分别映射到create, read, update and destroy。每个代理子类都实现了这些函数。
The CRUD methods each expect an Operation object as the sole argument. The Operation encapsulates information about the action the Store wishes to perform, the model instances that are to be modified, etc. See the Operation documentation for more details. Each CRUD method also accepts a callback function to be called asynchronously on completion.
CRUD方法都需要一个 Operation 对象作为参数。Operation封装了期望store执行的操作、需要修改的模型实例等信息。参阅Operation文档获取更多细节。每个CRUD方法还接受一个在操作完成时的异步回调函数作为参数。
create( operation, callback, scope )
read( operation, callback, scope )
update( operation, callback, scope )
Proxies also support batching of Operations via a batch object, invoked by the batch method.
通过batch对象,proxy还支持批量操作。
Ajax Ajax代理
AjaxProxy is one of the most widely-used ways of getting data into your application. It uses AJAX requests to load data from the server, usually to be placed into a Store. Let's take a look at a typical setup. Here we're going to set up a Store that has an AjaxProxy. To prepare, we'll also set up a Model:
ajax代理是在app中用的最广泛的方式。它使用ajax请求从服务器加载数据,通常被放在store中。让我们看看典型地设置。这里我们将建立一个使用ajax代理的store。作为准备,我们建立一个模型:
Ext.define('User', { extend: 'Ext.data.Model', fields: ['id', 'name', 'email'] }); //The Store contains the AjaxProxy as an inline configuration var store = Ext.create('Ext.data.Store', { model: 'User', proxy: { type: 'ajax', url : 'users.json' } }); store.load();
Our example is going to load user data into a Store, so we start off by defining a Model with the fields that we expect the server to return. Next we set up the Store itself, along with a proxy configuration. This configuration was automatically turned into an Ext.data.proxy.Ajax instance, with the url we specified being passed into AjaxProxy's constructor. It's as if we'd done this:
我们的示例将加载user数据到stroe中,我们从定义一个期望从服务器返回的model开始。接下来,我们建立了store,具有一个proxy配置。这个配置项自动创建一个Ext.data.proxy.Ajax 实例,配置的url作为AjaxProxy的构造函数参数传入。就好像我们像下面这样做的:
new Ext.data.proxy.Ajax({ url: 'users.json', model: 'User', reader: 'json' });
A couple of extra configurations appeared here - model and reader. These are set by default when we create the proxy via the Store - the Store already knows about the Model, and Proxy's default Reader is JsonReader.
这里出现了一对额外的配置,model and reader。这些配置是通过store创建代理是缺省配置的--store已经知道了模型、代理的缺省Reader 是 JsonReader。
Now when we call store.load(), the AjaxProxy springs into action, making a request to the url we configured ('users.json' in this case). As we're performing a read, it sends a GET request to that url (see actionMethods to customize this - by default any kind of read will be sent as a GET request and any kind of write will be sent as a POST request).
现在,当我们调用store.load(),ajaxproxy会发送一个请求道我们配置的url(这里是'users.json')。当我们正在执行read,它发生get请求道这个url(参阅actionMethods方法来自定义这点--缺省地,任何类型的read都是get请求,任何类型的write都是post请求 )。
Limitations 限制
AjaxProxy cannot be used to retrieve data from other domains. If your application is running on http://domainA.com it cannot load data from http://domainB.com because browsers have a built-in security policy that prohibits domains talking to each other via AJAX.
ajax代理不能用在跨域获取数据。如果你的app运行在 http://domainA.com,它不能从http://domainB.com 加载数据,因为浏览器在使用ajax时有个内置的安全策略来阻止域之间的交互。
If you need to read data from another domain and can't set up a proxy server (some software that runs on your own domain's web server and transparently forwards requests to http://domainB.com, making it look like they actually came from http://domainA.com), you can use Ext.data.proxy.JsonP and a technique known as JSON-P (JSON with Padding), which can help you get around the problem so long as the server on http://domainB.com is set up to support JSON-P responses. See JsonPProxy's introduction docs for more details.
如果你需要从其它域读取数据,并且建立一个代理服务(一种运行在你自己域中的软件,转发请求到http://domainB.com,使得看起来是对http://domainA.com的访问),你可以使用Ext.data.proxy.JsonP ,一种称为JSON-P 的技术,它可帮助你解决这个问题,通过在http://domainB.com 建立支持JSON-P 的响应。更多细节参考JsonPProxy。
Readers and Writers 读取器和写入器
AjaxProxy can be configured to use any type of Reader to decode the server's response. If no Reader is supplied, AjaxProxy will default to using aJsonReader. Reader configuration can be passed in as a simple object, which the Proxy automatically turns into a Reader instance:
ajax代理可配置使用任何类型的Reader来解码服务器的响应。如果没有提供reader,ajax会缺省使用JsonReader。reader的配置可通过一个简单对象来传入,proxy会自动将其转换为reader类实例:
var proxy = new Ext.data.proxy.Ajax({ model: 'User', reader: { type: 'xml', root: 'users' } }); proxy.getReader(); //returns an XmlReader instance based on the config we supplied
Url generation Url生成
AjaxProxy automatically inserts any sorting, filtering, paging and grouping options into the url it generates for each request. These are controlled with the following configuration options:
ajax代理自动插入任何排序、过滤、分页、分组选项到它生成的每个url请求中。这些由下面的配置选项提供:
- pageParam - controls how the page number is sent to the server (see also startParam and limitParam)控制页码
- sortParam - controls how sort information is sent to the server 排序
- groupParam - controls how grouping information is sent to the server 分组信息
- filterParam - controls how filter information is sent to the server 过滤
Each request sent by AjaxProxy is described by an Operation. To see how we can customize the generated urls, let's say we're loading the Proxy with the following Operation:
ajax发送的每个请求由一个 Operation对描述。我们看看如何定义生成的url:
var operation = new Ext.data.Operation({ action: 'read', page : 2 });
Now we'll issue the request for this Operation by calling read:
现在,通过调用read发送此请求:
var proxy = new Ext.data.proxy.Ajax({ url: '/users' }); proxy.read(operation); //GET /users?page=2
Easy enough - the Proxy just copied the page property from the Operation. We can customize how this page data is sent to the server:
很简单,proxy仅仅从Operation复制page属性。我们可以定义页码是如何发送到服务器的:
var proxy = new Ext.data.proxy.Ajax({ url: '/users', pageParam: 'pageNumber' }); proxy.read(operation); //GET /users?pageNumber=2
Alternatively, our Operation could have been configured to send start and limit parameters instead of page:
或者,Operation 可被配置来发送start和limit参数,而不是具体的页码:
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
Again we can customize this url:
我们可以再次自定义这个url:
var proxy = new Ext.data.proxy.Ajax({ url: '/users', startParam: 'startIndex', limitParam: 'limitIndex' }); proxy.read(operation); //GET /users?startIndex=50&limitIndex;=25
AjaxProxy will also send sort and filter information to the server. Let's take a look at how this looks with a more expressive Operation object:
ajax代理还会自动发送排序和过滤信息到服务器。让我们看看:
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' }) ] });
This is the type of object that is generated internally when loading a Store with sorters and filters defined. By default the AjaxProxy will JSON encode the sorters and filters, resulting in something like this (note that the url is escaped before sending the request, but is left unescaped here for clarity):
这是在加载包括排序和过滤定义的store时自动创建的对象。缺省的,ajax代理用json格式编码排序和过滤,结果如下面所示(注意url在发送时会转义,但是为了阅读这里是没有转义的)。
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"}]
We can again customize how this is created by supplying a few configuration options. Let's say our server is set up to receive sorting information is a format like "sortBy=name#ASC,age#DESC". We can configure AjaxProxy to provide that format like this:
我们可以再次通过配置项来自定义。我们的服务器接收形如"sortBy=name#ASC,age#DESC"的排序表达式。我们可以配置AjaxProxy提供此格式:
var proxy = new Ext.data.proxy.Ajax({ url: '/users', sortParam: 'sortBy', filterParam: 'filterBy', //our custom implementation of sorter encoding - turns our sorters into "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"}]
We can also provide a custom encodeFilters function to encode our filters.
我们还可以提供一个自定义的 encodeFilters函数来编码我们的过滤。