ExtJS4笔记 Data

The data package is what loads and saves all of the data in your application and consists of 41 classes, but there are three that are more important than all the others - ModelStore and Ext.data.proxy.Proxy. These are used by almost every application, and are supported by a number of satellite classes:

数据包加载并保存您的应用程序中的所有数据。它包括41类,但其中有三个,比其他的都重要 - Model, Store 和 Ext.data.proxy.Proxy。这些几乎每一个应用程序都会用到。这三个类还有些支持的卫星类:

Data package overview

 

Models and Stores

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. We’re going to look at four of the principal parts of Model — FieldsProxiesAssociations and Validations.

数据包的核心是Ext.data.Model。 Model代表应用程序中的一些类型数据 - 例如一个电子商务应用程序可能会有Users, Products 和 Orders模型。最简单的一个模型仅仅是一个字段和他们的数据。我们要看看模型的四个主要部分— Fields, Proxies, Associations 和Validations 。

 

Model architecture

 

Let's look at how we create a model now:让我们看看怎么创建一个Model:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'id', type: 'int' },
        { name: 'name', type: 'string' }
    ]
});

 

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:

Models通常会用到Store,Store基本上是Models实例的一个集合。建立一个Store和加载其数据很简单:

Ext.create('Ext.data.Store', {
    model: 'User',
    proxy: {
        type: 'ajax',
        url : 'users.json',
        reader: 'json'
    },
    autoLoad: true
});

 

We configured our Store to use an Ajax Proxy, telling it the url to load data from and the Reader used to decode the data. In this case our server is returning JSON, so we've set up a Json Reader to read the response. The store auto-loads a set of User model instances from the url users.json. Theusers.json url should return a JSON string that looks something like this:

我们配置Store使用Ajax Proxy,告诉它加载数据的URL,并用一个Reader解析数据。在这种情况下,我们的服务器返回JSON,所以我们创建一个JSON Reader来读取响应。Store从URL users.json中自动加载User model实例集合。 users.json URL应该返回一个JSON字符串,看起来像这样:

{
    success: true,
    users: [
        { id: 1, name: 'Ed' },
        { id: 2, name: 'Tommy' }
    ]
}

 

For a live demo please see the Simple Store example.

 Simple Store例子里有现场演示。

Inline data

Stores can also load data inline. Internally, Store converts each of the objects we pass in as data into Model instances:

Store也可以载入内联的数据。在内部,Store转换每个作为data (数据)传递到Model实例的对象:

Ext.create('Ext.data.Store', {
    model: 'User',
    data: [
        { firstName: 'Ed',    lastName: 'Spencer' },
        { firstName: 'Tommy', lastName: 'Maintz' },
        { firstName: 'Aaron', lastName: 'Conran' },
        { firstName: 'Jamie', lastName: 'Avins' }
    ]
});

 

Inline Data example

Sorting and Grouping

Stores are able to perform sorting, filtering and grouping locally, as well as supporting remote sorting, filtering and grouping:

Stores能够执行本地排序、过滤和分组,以及支持远程排序,过滤和分组:

Ext.create('Ext.data.Store', {
    model: 'User',

    sorters: ['name', 'id'],
    filters: {
        property: 'name',
        value   : 'Ed'
    },
    groupField: 'age',
    groupDir: 'DESC'
});

 

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 in descending order. It's easy to change the sorting, filtering and grouping at any time through the Store API. For a live demo, see theSorting Grouping Filtering Store example.

在我们刚刚创建的Store中,数据将首先由名称,然后由ID进行排序,它会过滤为只包括name为“Ed”的数据,并且数据按照年龄分组降序排列。通过Store API很容易在任何时间改变排序,过滤和分组。现场演示,请参阅 Sorting Grouping Filtering Store例子。

Proxies

Proxies are used by Stores to handle the loading and saving of Model data. There are two types of Proxy: Client and Server. Examples of client proxies include Memory for storing data in the browser's memory and Local Storage which uses the HTML 5 local storage feature when available. Server proxies handle the marshaling of data to some remote server and examples include Ajax, JsonP and Rest.

代理用于Store,处理载入和保存模型数据。有两种类型的代理:客户端和服务器端。客户端代理的例子包括在浏览器的内存和HTML 5的本地存储功能可用时。服务器端代理封装处理一些远程服务器数据,其中包括Ajax,Json和Rest。

Proxies can be defined directly on a Model like so:

代理可以在Model中直接定义,像这样:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'age', 'gender'],
    proxy: {
        type: 'rest',
        url : 'data/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    }
});

// Uses the User Model's Proxy
Ext.create('Ext.data.Store', {
    model: 'User'
});

 

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 model的Stroe都需要以同样的方式加载数据,这样就使我们避免重复定义每个Stroe的Proxy。第二,我们现在不需要Store就可以载入和保存模型Model:

// Gives us a reference to the User class
var User = Ext.ModelMgr.getModel('User');

var ed = Ext.create('User', {
    name: 'Ed Spencer',
    age : 25
});

// We can save Ed directly without having to add him to a Store first because we
// configured a RestProxy this will automatically send a POST request to the url /users
ed.save({
    success: function(ed) {
        console.log("Saved Ed! His ID is "+ ed.getId());
    }
});

// Load User 1 and do something with it (performs a GET request to /users/1)
User.load(1, {
    success: function(user) {
        console.log("Loaded user 1: " + user.get('name'));
    }
});

 

There are also Proxies that take advantage of the new capabilities of HTML5 - LocalStorage and SessionStorage. Although older browsers don't support these new HTML5 APIs, they're so useful that a lot of applications will benefit enormously from their presence.

也有利用HTML5新功能优势的代理, -LocalStorage 和SessionStorage。虽然旧的浏览器不支持HTML5的这些新API,但是这个技术前景极好。

Example of a Model that uses a Proxy directly

Associations

Models can be linked together with the 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:

Models可以用Associations API联系在一起。大多数应用程序处理许多不同的Models,Models几乎都是相关的。一个博客应用程序可能有User,Post和CommentModel。用户可以创建文章,文章可以收到评论。我们可以像这样表达这些关系:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name'],
    proxy: {
        type: 'rest',
        url : 'data/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    },

    hasMany: 'Post' // shorthand for { model: 'Post', name: 'posts' }
});

Ext.define('Post', {
    extend: 'Ext.data.Model',
    fields: ['id', 'user_id', 'title', 'body'],

    proxy: {
        type: 'rest',
        url : 'data/posts',
        reader: {
            type: 'json',
            root: 'posts'
        }
    },
    belongsTo: 'User',
    hasMany: { model: 'Comment', name: 'comments' }
});

Ext.define('Comment', {
    extend: 'Ext.data.Model',
    fields: ['id', 'post_id', 'name', 'message'],

    belongsTo: 'Post'
});

 

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:

可以很容易地表达您的应用程序中的不同Models之间的丰富关系。每个模型可以有任意数量的Associations与其他Models关联,Models可以按照任何的顺序定义。一旦我们有一个Models的实例,我们可以很容易地遍历相关的数据 - 例如,如果我们想记录每个文章上给定用户的所有评论,我们可以这样做:

// Loads User with ID 1 and related posts and comments using User's Proxy
User.load(1, {
    success: function(user) {
        console.log("User: " + user.get('name'));

        user.posts().each(function(post) {
            console.log("Comments for post: " + post.get('title'));

            post.comments().each(function(comment) {
                console.log(comment.get('message'));
            });
        });
    }
});

 

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关联的结果都会产生一个新的函数添加到Model中。我们定义User model hasMany Posts,会新增user.posts()函数供我们在上面的代码片段使用。调用guser.posts()返回Post model的 Store配置。反过来,Post model获取comments() 函数是因为我们设置的Comments的hasMany关联。

Associations aren't just helpful for loading data - they're useful for creating new records too:

关联不仅仅用于加载数据 – 创建新纪录的时候也非常有用:

user.posts().add({
    title: 'Ext JS 4.0 MVC Architecture',
    body: 'It\'s a great Idea to structure your Ext JS Applications using the built in MVC Architecture...'
});

user.posts().sync();

 

Here we instantiate a new Post, which is automatically given the User's id in the user_id field. Calling sync() saves the new Post via its configured Proxy - this, again, is an asynchronous operation to which you can pass a callback if you want to be notified when the operation completed.

在这里,我们实例化一个新的Post(文章),user_id字段会自动填充上用户ID。调用sync()通过其配置的Proxy保存新Post - 这又是一个异步操作。如果你想操作完成时发送通知,也可以添加一个回调(callback)。

The belongsTo association also generates new methods on the model, here's how we can use those:

belongsTo关联也可以生成新的Model方法,可以这样使用这些方法:

// get the user reference from the post's belongsTo association
post.getUser(function(user) {
    console.log('Just got the user reference from the post: ' + user.get('name'))
});

// try to change the post's user
post.setUser(100, {
    callback: function(product, operation) {
        if (operation.wasSuccessful()) {
            console.log('Post\'s user was updated');
        } else {
            console.log('Post\'s user could not be updated');
        }
    }
});

 

Once more, the loading function (getUser) is asynchronous and requires a callback function to get at the user instance. The setUser method simply updates the foreign_key (user_id in this case) to 100 and saves the Post model. As usual, callbacks can be passed in that will be triggered when the save operation has completed - whether successful or not.

再次,加载函数(getUser)是异步的,需要一个回调函数来获取用户实例。setUser方法只需更新foreign_key(这里是user_id)为100并保存Post model。像往常一样,可以在已完成保存操作时触发回调- 无论成功与否。

Loading Nested Data

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. This is because the above example assumes that when we make a request to get a user the server returns the user data in addition to all of its nested Posts and Comments. 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.load的调用,但在访问用户的文章和评论时却没有这样做。这是因为上面的例子中假定,当我们提出请求获取一个用户,服务器返回的用户数据会嵌套所有的文章和评论。通过设立象我们上面那样的关联,框架可以自动解析出嵌套在单一请求中的数据。框架不是先获取用户数据,然后调用另一个请求获取文章数据,然后再发出更多的请求获取评论,而是在一个服务器响应里返回所有数据:

{
    success: true,
    users: [
        {
            id: 1,
            name: 'Ed',
            age: 25,
            gender: 'male',
            posts: [
                {
                    id   : 12,
                    title: 'All about data in Ext JS 4',
                    body : 'One areas that has seen the most improvement...',
                    comments: [
                        {
                            id: 123,
                            name: 'S Jobs',
                            message: 'One more thing'
                        }
                    ]
                }
            ]
        }
    ]
}

 

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.

数据全部是框架自动分析的。可以很容易地配置Model的代理加载任何地方的数据,用他们的Reader来处理几乎任何返回的格式。至于Ext JS3,整个框架的许多组件都用到了Model和Store,如Grids, Trees and Forms。

See the Associations and Validations demo for a working example of models that use relationships.

Associations and Validations 演示了Model的使用。

Of course, it's possible to load your data in a non-nested fashion. This can be useful if you need to "lazy load" the relational data only when it's needed. Let's just load the User data like before, except we'll assume the response only includes the User data without any associated Posts. Then we'll add a call to user.posts().load() in our callback to get the related Post data:

当然,它可以用非嵌套的方式来加载数据。如果你需要“懒加载(只有被需要的时候才会加载)”,这就会有用了。我们只是像以前那样加载User数据,但我们假设响应只包含User数据而没有任何关联的Post。然后,我们将在回调中添加一个调用user.posts().load()的方法,以获得相关的Post数据。

// Loads User with ID 1 User's Proxy
User.load(1, {
    success: function(user) {
        console.log("User: " + user.get('name'));

        // Loads posts for user 1 using Post's Proxy
        user.posts().load({
            callback: function(posts, operation) {
                Ext.each(posts, function(post) {
                    console.log("Comments for post: " + post.get('title'));

                    post.comments().each(function(comment) {
                        console.log(comment.get('message'));
                    });
                });
            }
        });
    }
});

 

For a full example see Lazy Associations

Validations

As of Ext JS 4 Models became a lot richer with support for validating their data. To demonstrate this we're going to build upon the example we used above for associations. First let's add some validations to the User model:

Ext JS4Model的数据验证变得更丰富了很多。为了证明这一点,我们要用上述关联的例子。首先,让我们添加一些验证的User model: 

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ...,

    validations: [
        {type: 'presence', name: 'name'},
        {type: 'length',   name: 'name', min: 5},
        {type: 'format',   name: 'age', matcher: /\d+/},
        {type: 'inclusion', name: 'gender', list: ['male', 'female']},
        {type: 'exclusion', name: 'name', list: ['admin']}
    ],

    proxy: ...
});

 

Validations follow the same format as field definitions. In each case, we specify a field and a type of validation. The validations in our example are expecting the name field to be present and to be at least 5 characters in length, the age field to be a number, the gender field to be either "male" or "female", and the username to be anything but "admin". Some validations take additional optional configuration - for example the length validation can take min and max properties, format can take a matcher, etc. There are five validations built into Ext JS and adding custom rules is easy. First, let's meet the ones built right in:

验证字段定义遵循相同的格式。在每一种情况下,我们指定一个字段和验证的类型。希望在我们的例子验证name字段必须存在至少5个字符长度,age字段是一个数字,gender(性别)字段要么是“male”要么是“female”,username可以是除了“admin”的任何东西。一些验证采取额外的可选配置 - 例如长度验证可以采取Min和Max属性,格式可以用正则表达式等等。有五个Ext JS的内置验证,添加自定义的规则也很容易。首先,让我们看看内置验证:

  • presence simply ensures that the field has a value. Zero counts as a valid value but empty strings do not.确保该字段有一个值。计数0有效,但是空字符串无效。
  • length ensures that a string is between a min and max length. Both constraints are optional.确保一个字符串在最小和最大长度之间。这两种约束是可选的. 
  • format ensures that a string matches a regular expression format. In the example above we ensure that the age field consists only of numbers.确保一个字符串匹配一个正则表达式格式。在上面的例子中,我们必须确保年龄字段是由至少一个字母后面跟4个数字组成(译者:这里可能有错误?)。
  • inclusion ensures that a value is within a specific set of values (e.g. ensuring gender is either male or female).确保值是特定的值(例如确保性别是男性或女性)。
  • exclusion ensures that a value is not one of the specific set of values (e.g. blacklisting usernames like 'admin').确保不是某值(例如列入黑名单的username,像是“admin”)。

Now that we have a grasp of what the different validations do, let's try using them against a User instance. We'll create a user and run the validations against it, noting any failures:

现在,我们已经掌握了不同的验证都是做什么的,让我们尝试对用户实例中使用它们。我们将创建一个用户,并针对它运行验证,并指出任何错误:

// now lets try to create a new user with as many validation errors as we can
var newUser = Ext.create('User', {
    name: 'admin',
    age: 'twenty-nine',
    gender: 'not a valid gender'
});

// run some validation on the new user we just created
var errors = newUser.validate();

console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errors
console.log('All Errors:', errors.items); //returns the array of all errors found on this model instance

console.log('Age Errors:', errors.getByField('age')); //returns the errors for the age field

 

The key function here is validate(), which runs all of the configured validations and returns an Errors object. This simple object is just a collection of any errors that were found, plus some convenience methods such as isValid() - which returns true if there were no errors on any field - andgetByField(), which returns all errors for a given field.

这里的主要是validate()方法,它运行所有配置的验证,并返回一个错误对象。这个简单的对象只是一个任何被发现的错误的集合。还有一些方便的方法,比如isValid(),如果任何字段都没有错误就返回true。  getByField(),它返回一个给定字段中的所有错误。

For a complete example that uses validations please see Associations and Validations

这里的主要是validate()方法,它运行所有配置的验证,并返回一个错误对象。这个简单的对象只是一个任何被发现的错误的集合。还有一些方便的方法,比如isValid(),如果任何字段都没有错误就返回true。  getByField(),它返回一个给定字段中的所有错误。

转载于:https://www.cnblogs.com/jimcheng/p/4272057.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值