One of the areas that has seen the most improvement in Ext JS 4 is the data package. The data package enables you to retrieve, decode and use data in your applications. The data package has been completely rewritten for version 4, but it uses the same approach as previous versions. Today we’re going to take a look at the new data package and see what it offers.
数据包在某种意义上来说是Ext JS 4中最完善的地方。数据包可以让你的应用程序对数据进行复用、解码和输出。在Ext JS 4中,数据包已经被重写,但它的使用方法与以前版本的一样。今天,我们将介绍新的数据包,看看它能为我们提供什么。
新特性
The data package in Ext JS 4 consists of 43 classes, but there are three that are more important than all others – Model, Store and Proxy. These are used by almost every application, and are supported by a number of satellite classes:
Ext JS 4的数据包包含43个类,但有Model 、Store和Proxy相对其它类来说相当重要,这几乎是每一个应用程序都要用到的,而且它有一些卫星类支持。
Models类和Store类
The centerpiece of the data package is Ext.data.Model. A Model represents some type of data in an application – for example an e-commerce app might have models for Users, Products and Orders. At its simplest a Model is just a set of fields and their data. Anyone familiar with Ext JS 3 will have used Ext.data.Record, which was the precursor to Ext.data.Model. Let’s look at how we create a model now:
数据包的核心是Ext.data.Model对象。一个模型就代表一个应用程序中的数据类型,例如一个电子商务应用程序可能包含用户、产品和订单等模型。最简单的一个模型只是一个字段和他么数据的集合。任何使用过Ext JS 3的人都会使用到Ext.data.Record,这就是Ext.data.Model的前身。让我们来看看如何创建一个模型:
1 | Ext . regModel ( ' User ' , { |
2 | fields : [ |
3 | { name : ' id ' , type : ' int ' } , |
4 | { name : ' name ' , type : ' string ' } |
5 | ] |
6 | } ) ; |
Models are typically used with a Store, which is basically a collection of Model instances. Setting up a Store and loading its data is simple:
模型通常使用于Store,基本上是一个模型实例的集合。Store的定义和加载很简单,代码如下:
1 | new Ext . data . Store ( { |
2 | model : ' User ' , |
3 | proxy : { |
4 | type : ' ajax ' , |
5 | url : ' users . json ' , |
6 | reader : ' json ' |
7 | } , |
8 | autoLoad : true |
9 | } ) ; |
That’s all we need to do to load a set of User model instances from the url ‘users.json’. We configured our Store to use an AjaxProxy, telling it the url to load data from and the Ext.data.Reader class used to decode the data. In this case our server is returning json, so we’ve set up a JsonReader to read the response.
代码中,我们从“users.json”加载了一个用户模型实例。在Store中,我们定义了一个Ajaxproxy,需要为它指定url以加载数据的地址,还要指定Ext.data.Reader解码数据的方式、例子中,服务器将返回json数据,因而我们需要使用JsonReader读取数据。
Stores are able to perform sorting, filtering and grouping locally, as well as supporting remote sorting, filtering and grouping. With Ext JS 4, there is no longer a separate GroupingStore – we can now do multi-sorting, filtering and grouping inside a standard Store:
Store不但支持本地排序、筛选和分组,也支持远程排序、筛选和分组。在Ext JS 4中,不再使用GroupingStroe,我们在标准的Store中就可以实现多列排序、筛选和分组:
1 | new Ext . data . Store ( { |
2 | model : ' User ' , |
3 | |
4 | sorters : [ ' name ' , ' id ' ] , |
5 | filters : { |
6 | property : ' name ' , |
7 | value : ' Ed ' |
8 | } , |
9 | groupers : { |
10 | property : ' age ' , |
11 | direction : ' ASC ' |
12 | } |
13 | } ) ; |
In the store we just created, the data will be sorted first by name then id; it will be filtered to only include Users with the name ‘Ed’ and the data will be grouped by age. It’s easy to change the sorting, filtering and grouping at any time through the Store API.
在代码中,数据将首先根据“name”字段排序,然后再按“id”排序;数据将筛选出“name”字段为“Ed”的数据,并对其按“age”字段进行分组。通过Store API,你可以在任何时间轻松地对数据进行排序、筛选和分组。
We saw above how Store uses a Proxy to load its data, and how that Proxy could in turn be configured with a Reader to decode the server response. One structural change in Ext JS 4 is that Store no longer has a direct link to Reader and Writer – these are now handled by the Proxy. This gives us an enormous benefit – Proxies can now be defined directly on a Model:
从上面的代码中可以看到,Store通过Proxy来加载数据以及在Proxy中定义的Reader对服务器返回的数据进行解码。Store在Ext JS 4中一个结构性的变化就是不再直接关联Reader和Writer,这些都将由Proxy处理。这带给了我们一个好处,就是在Model中可以直接定义Proxies:
1 | Ext . regModel ( ' User ' , { |
2 | fields : [ ' id ' , ' name ' , ' age ' ] , |
3 | proxy : { |
4 | type : ' rest ' , |
5 | url : ' / users ' , |
6 | reader : { |
7 | type : ' json ' , |
8 | root : ' users ' |
9 | } |
10 | } |
11 | } ) ; |
12 | |
13 | // uses the User Model's Proxy |
14 | new Ext . data . Store ( { |
15 | model : ' User ' |
16 | } ) ; |
This helps us in two ways. First, it’s likely that every Store that uses the User model will need to load its data the same way, so we avoid having to duplicate the Proxy definition for each Store. Second, we can now load and save Model data without a Store:
这带来了两个好处。第一,因为每个使用User模型的Store都使用同一方式加载数据,从而避免了为每个Sotre重复定义Proxy。第二,现在我们不需要通过Store,就可以直接在模型中加载和保存数据了:
1 | // gives us a reference to the User class |
2 | var User = Ext . getModel ( ' User ' ) ; |
3 | |
4 | var ed = new User ( { |
5 | name : ' Ed Spencer ' , |
6 | age : 25 |
7 | } ) ; |
8 | |
9 | // we can save Ed directly without having to add him to a Store first because we |
10 | // configured a RestProxy this will automatically send a POST request to the url /users |
11 | ed . save ( { |
12 | success : function ( ed ) { |
13 | console . log ( " Saved Ed! His ID is " + ed . getId ( ) ) ; |
14 | } |
15 | } ) ; |
16 | |
17 | // load User 123 and do something with it (performs a GET request to /users/123) |
18 | User . load ( 123 , { |
19 | success : function ( user ) { |
20 | console . log ( " Loaded user 123: " + user . get ( ' name ' ) ) ; |
21 | } |
22 | } ) ; |
We’ve also introduced some brand new Proxies that take advantage of the new capabilities of HTML5 – LocalStorageProxy and SessionStorageProxy. Although older browsers don’t support these new HTML5 APIs, they’re so useful that we know a lot of applications will benefit enormously from their presence. And if we don’t have a Proxy that matches your needs it’s easy to create your own.
在这里我们需要介绍一下采用HTML 5新功能的代理LocalStorageProxy和SessionStorageProxy。尽管旧的浏览器不支持这些HTML 5的API,但它们非常有用,但它们的存在,会让我们获益良多。如果没有符合你要求的proxy,你可以轻松的创建你需要的Proxy。
模型关联
Proxies aren’t the only new capability added to Models; we can now link Models together with the new Associations API. Most applications deal with many different Models, and the Models are almost always related. A blog authoring application might have models for User, Post and Comment. Each User creates Posts and each Post receives Comments. We can express those relationships like so:
在模型中定义Proxy不是唯一的新功能,我们现在还可以通过关联API将模型关联起来。大多数应用程序会处理许多不同的模型,而且模型之间是相关的。譬如,一个博客应用包括用户、发布和评论等模型。每个用户发布的文章及它的评论,我们可以这样表达它们之间的关系:
1 | Ext . regModel ( ' User ' , { |
2 | fields : [ ' id ' , ' name ' ] , |
3 | |
4 | hasMany : ' Posts ' |
5 | } ) ; |
6 | |
7 | Ext . regModel ( ' Post ' , { |
8 | fields : [ ' id ' , ' user_id ' , ' title ' , ' body ' ] , |
9 | |
10 | belongsTo : ' User ' , |
11 | hasMany : ' Comments ' |
12 | } ) ; |
13 | |
14 | Ext . regModel ( ' Comment ' , { |
15 | fields : [ ' id ' , ' post_id ' , ' name ' , ' message ' ] , |
16 | |
17 | belongsTo : ' Post ' |
18 | } ) ; |
It’s easy to express rich relationships between different Models in your application. Each Model can have any number of associations with other Models and your Models can be defined in any order. Once we have a Model instance we can easily traverse the associated data – for example, if we wanted to log all Comments made on each Post for a given User, we can do something like this:
这很容易表达出您的应用程序的不同模型之间的复杂关系。每一个模型不单可以拥有许多关联模型,而且与它们的定义顺序无关。一旦我们有一个模型实例,我们就可以很容易地遍历相关数据。 例如,如果我们想输出一个用户的全部文章的评论,我们可以这样做:
1 | // loads User with ID 123 using User's Proxy |
2 | User . load ( 123 , { |
3 | success : function ( user ) { |
4 | console . log ( " User: " + user . get ( ' name ' ) ) ; |
5 | |
6 | user . posts ( ) . each ( function ( post ) { |
7 | console . log ( " Comments for post: " + post . get ( ' title ' ) ) ; |
8 | |
9 | post . comments ( ) . each ( function ( comment ) { |
10 | console . log ( comment . get ( ' message ' ) ) ; |
11 | } ) ; |
12 | } ) ; |
13 | } |
14 | } ) ; |
Each of the hasMany associations we created above results in a new function being added to the Model. We declared that each User model hasMany Posts, which added the user.posts() function we used in the snippet above. Calling user.posts() returns a Store configured with the Post model. In turn, the Post model gets a comments() function because of the hasMany Comments association we set up.
每当定义一个hasMany关联的时候,我们都将在模型内增加一个新函数。因为我们在User模型和Posts模型中定义hasMany关联,所以在User模型中增加了上面代码中的user.posts()函数。调用user.posts()将返回一个使用Post模型的Store。同样,因为Post模型和Comments模型建立了hasMany关联,所以在Post模型中可以使用comments函数。
You may be wondering why we passed a ‘success’ function to the User.load call but didn’t have to do so when accessing the User’s posts and comments. All data is assumed to be loaded asynchronously because it usually has to be loaded from a server somewhere. This usually means passing in callbacks that are called when the data has been loaded, as with the ‘success’ function above.
你可能很奇怪,为什么在User.load中需要使用“success”函数,而在post和comments函数中不需要?这是因为所有数据都被假定为从服务器上异步加载的。这意味着当所有数据都已经被加载时,才会回调上面代码的“success”函数。
加载嵌套数据
By setting up associations as we did above, the framework can automatically parse out nested data in a single request. Instead of making a request for the User data, another for the Posts data and then yet more requests to load the Comments for each Post, we can return all of the data in a single server response like this:
当我们在建立上面的关联时,框架会自动分析出单个请求中的嵌套数据。譬如我们请求一个User数据,它的Post数据以及每个Post数据的Comments数据都会从一个服务器请求中返回,数据形式如下:
1 | { |
2 | id : 1 |
3 | name : ' Ed ' , |
4 | posts : [ |
5 | { |
6 | id : 12 , |
7 | title : ' All about data in Ext JS 4 ' , |
8 | body : ' One of the areas that has seen the most improvement in Ext JS 4 . . . ' , |
9 | comments : [ |
10 | { |
11 | id : 123 , |
12 | name : ' S Jobs ' , |
13 | message : ' One more thing ' |
14 | } |
15 | ] |
16 | } |
17 | ] |
18 | } |
The data is all parsed out automatically by the framework. It’s easy to configure your Models’ Proxies to load data from almost anywhere, and their Readers to handle almost any response format. As with Ext JS 3, Models and Stores are used throughout the framework by many of the components such a Grids, Trees and Forms.
因为这些数据都是通过框架自动分析处理的,因而你可以很方便的配置模型的Proxy从任何地方加载数据以及使用不同的Reader处理不同格式的数据。至于Ext JS 3,Models和Stores都是通过许多组件框架使用的,譬如网格、树和表单。
在线演示和更多
We’ve set up a simple live demo for you to experiment with and placed it online. The demo uses the same Models that we set up in this post, but runs live code against a dummy data set. You can also download the live demo’s source code and experiment yourself. We’re currently in beta so there may be occasional bugs, but in general the data package is in a very robust state.
我们已经为你主板了一个简单的在线演示让你体验新的数据包功能。该演示使用了本文模型的设置和对应的数据。你也能下载该演示在本地运行。因为当时还处于测试阶段,因而会有一些bug,但总体来说,数据包处于一个非常强壮的状态。
To find out even more about the new data package and its new capabilities, I’d like to encourage you to sign up to our newsletter. We send it out about once a month and it always contains new articles on Ext JS and Sencha Touch that you can’t find anywhere else (even on our blog) — Sign up at the top of this page .
如果你想了解更多有关新的数据包的功能,我估计你注册我们的新闻列表。我们讲每月发送一次关于Ext JS和Sencha Touch的文章,有些文章是你在其它地方找不到的(包括我们的博客)。
原文:http://www.sencha.com/blog/2011/01/21/countdown-to-ext-js-4-data-package/