Sencha ExtJS5.x 的数据包Data Package讲解

数据包是你应用程序加载和保存所有数据的地方。它包含大量的类,其中有三个比其它所有的都更重要。

它们是: Ext.data.Model / Store /Ext.data.proxy.Proxy

这三个类几乎被所有的应用程序使用,并且得到了许多周围类来支持。


data package

Models模型

数据包的核心就是Ext.data.Model.一个模型就在应用程序中代表了一个实体,举个例子,一个电子商务应用程序可能需要有用户、商品和订单,最基本的层次上来说,一个模型就定义了一系列的字段和其相关联的业务逻辑。

我们可以看一下模型的几个主要部分:

Fields/ Proxies/ Validations/Associations


模型组成

创建一个模型

通常来说,使用一个基类来定义你的模型是一个好的选择。这个基类可以方便你在一个地方对你的模型进行特定的配置,这样也方便配置schema,schema是你应用程序所有模型的管理器,现在我们可以先重点关注下两个比较有用的配置选项:

Ext.define('MyApp.model.Base',{

    extend: 'Ext.data.Model',


    fields: [{

        name: 'id',

        type: 'int'

    }],


    schema: {

        namespace: 'MyApp.model',  // generate auto entityName


        proxy: {     // Ext.util.ObjectTemplate

            type: 'ajax',

            url: '{entityName}.json',

            reader: {

                type: 'json',

                rootProperty:'{entityName:lowercase}'

            }

        }

    }

});

不同的应用程序在基类模型中会有不同的内容,尤其是fields.

Proxies代理

代理是在Models和Stores中使用的,它负责加载和保存模型的数据。有两种不同类型的代理:客户端和服务端(Client And Server).

代理可以直接在基类model的schema中定义,比如上面的代码例子。

客户端代理

客户端的例子有Memory和Local

Storage,使用了HTML5的localstorage特性。尽管旧的浏览器不支持这些新的HTML5 AP,但是它在实际应用中是非常有用的。

服务端代理

服务端代理负责封装远程服务的数据,例子有AJAX/JSONP/REST。

Schema

Schema是一系列有彼此关联的实体。当一个模型配置了schema,所有的衍生类都会继承。上述例子中,schema已经默认给所有的模型配置了两个默认属性。

第一个配置是namespace命名空间,通过指定这个命名空间,所有实体都拥有了一个缩略名,缩略名在定义实体关联关系的时候非常重要。

第二个配置是 代理proxy,这是一个类模板,跟Ext.XTemplete有点类似。不同的就是类模板在给定数据的时候产生的是对象,在此指定之后,没有显示指定proxy的都会使用该proxy.

应用程序中很可能会存在这种微小差异但又绝大多数相同的请求,通过这样配置,可以减少每个模型直接的重复定义proxy。

User.json被我们指定为url:{entityName.json},应该返回JSON字符串。在例子中我们使用的是

{

  "success": "true",

  "user": [

    {

      "id": 1,

      "name": "Philip J.Fry"

    },

    {

      "id": 2,

      "name": "HubertFarnsworth"

    },

    {

      "id": 3,

      "name": "TurangaLeela"

    },

    {

      "id": 4,

      "name": "Amy Wong"

    }

  ]

}

Stores

通常情况下model模型会配合store一起使用,store是一系列的records记录的集合,而record是一个模型驱动的类的实例,下面的例子是一个创建store和加载数据的:

var store = new Ext.data.Store({

    model: 'MyApp.model.User'

});


store.load({

    callback:function(){

        var first_name =this.first().get('name');

         console.log(first_name);

    }

});

我们手动加载store来获取一系列的MyApp.model.User的记录,这些记录在加载完成后会在回调事件中打印出来。

内联数据Inline data

Store可以加载内联数据,store根据我们传入的对象加载到模型适合的类型中去。

new Ext.data.Store({

    model: 'MyApp.model.User',

    data: [{

        id: 1,

        name: "Philip J. Fry"

    },{

        id: 2,

        name: "Hubert Farnsworth"

    },{

        id: 3,

        name: "Turanga Leela"

    },{

        id: 4,

        name: "Amy Wong"

    }]

});

排序和分组

Stores可以执行排序,分组和过滤,可以是本地的也可以是服务端的。

new Ext.data.Store({

    model: 'MyApp.model.User',


    sorters: ['name','id'],

    filters: {

        property: 'name',

        value  : 'Philip J. Fry'

    }

});

在这个store中,数据通过name和id排序,数据会过滤只加载包含Philip J. Fry的用户,通过API可以随时对这些属性进行调整修改。

Associations关联关系

模型可以通过关联关系API聚合到一起,多数应用程序会处理很多模型,并且模型直接存在关系。一个授权博客程序可能会有用户和发稿,每一个用户创建很多稿件,所以一个用户可能会存在多个发稿,但是一个稿件只能被一个用户发布,这就是大家熟知的多对一关系,我们在ExtJS中这样表达:

Ext.define('MyApp.model.User',{

    extend: 'MyApp.model.Base',


    fields: [{

        name: 'name',

        type: 'string'

    }]

});


Ext.define('MyApp.model.Post',{

    extend: 'MyApp.model.Base',


    fields: [{

        name: 'userId',

        reference: 'User', // the entityNamefor MyApp.model.User

        type: 'int'

    }, {

        name: 'title',

        type: 'string'

    }]

});

在应用程序中对丰富的关系模型进行表述可以说是很方便了。每一个模型都可以有任意数量的对其他模型的关联关系。另外,你的模型定义的顺序也可以比较随意,一旦你有了这个模型的类型,你就可以方便的遍历关联数据了。比如,你想获取一个用户所有的发稿,你就可以这样做:

// Loads User with ID 1 andrelated posts and comments

// using User's Proxy

MyApp.model.User.load(1, {

    callback: function(user) {

        console.log('User: ' +user.get('name'));


        user.posts(function(posts){

            posts.each(function(post) {

                console.log('Post: ' +post.get('title'));

            });

        });

    }

});

上述代码是说,model新增了一个方法user.posts(),每一个用户都有许多发稿,调用user.posts()就会返回Post模型配置的store。

关联关系不仅在加载数据的时候有用,在创建新的记录的时候也可以用:

user.posts().add({

    userId: 1,

    title: 'Post 10'

});


user.posts().sync();

这个实例创建了一个新的发稿,自动赋值用户ID给ID字段,调用sync()方法通过proxy保存新的发稿,这是异步的方法,所以你可以设置当完成操作的时候进行回调。

逆关联关系在Post模型中也会产生新的方法:

MyApp.model.Post.load(1, {

    callback: function(post) {


        post.getUser(function(user) {

            console.log('Got user from post: '+ user.get('name'));

        });                          

    }

});


MyApp.model.Post.load(2, {

    callback: function(post) {

        post.setUser(100);                        

    }

});

加载方法getUser()是异步的,需要一个回调来创建用户实例,setUser()方法仅仅就是更新了用户id为100并且保存了Post模型,跟以前一样,可以通过保存操作的返回成功与否触发回调。

加载嵌入数据

当关联关系定义好之后,单请求可以同时请求到关联数据,比如,看下面的返回值;{

    "success": true,

    "user": [{

        "id": 1,

        "name": "Philip J.Fry",

        "posts": [{

            "title": "Post1"

        },{

            "title": "Post2"

        },{

            "title": "Post3"

        }]

    }]

}

通过单请求,可以同时获取用户和用户下的文章,儿不必先请求用户,再根据用户获取下面的发稿。

验证

模型同时也提供了对数据校验的一大群支持,为了进行演示,我们通过上述例子进行构造数据,我们给用户模型增加了一些数据校验:

Ext.define('MyApp.model.User',{

    extend: 'Ext.data.Model',

    fields: ...,


    validators: {

        name: [

            'presence',

            { type: 'length', min: 7 },

            { type: 'exclusion', list: ['Bender']}

        ]

    }

});

校验定义一个name字段,对该字段进行校验,校验规则就是name字段下配置的对象,例子说的是对name字段进行校验,校验规则是长度不得少于7个字符,数据可以是除了Bender之外的任何数据。

有些严重包含其他一些配置选择,比如长度可以有最长和最短,max min属性,格式化可以使用matcher等,ExtJS提供了五个校验,用户自定义校验也很简单:

Presence-确保该字段必须存在值,不允许有空字符串。

Length-确保字符串有正确的长度,最大最小都是可选的。

Format-确保字符串满足正则表达式的格式。

Inclusion-确保值包含我们要求的。

Exclusion-确保值不包含我们要求的。

下面可以通过用户实例来尝试使用校验,我们创建一个用户,进行校验的:

// now lets try to create anew user with as many validation

// errors as we can

var newUser = newMyApp.model.User({

    id: 10,

    name: 'Bender'

});


// run some validation on thenew user we just created

console.log('Is User valid?',newUser.isValid());


//returns 'false' as therewere validation errors


var errors =newUser.getValidation(),

    error = errors.get('name');


console.log("Error is:" + error);

关键方法就是getValidation(),通过该方法进行校验和返回校验结果,校验记录是懒加载的并且需要的时候才更新。

上面的结果是:Length must be greater than 7

所以我们提供一个大于7个字符的字符:

newUser.set('name', 'BenderBending Rodriguez');

errors =newUser.getValidation();

这样,所有条件都被满足了,调用newUser.isValid()返回true,当我们调用getValidation()就能保证字段都是正常的了。

你可能感兴趣的:(Sencha ExtJS5.x 的数据包Data Package讲解)