【ExtJS 4.x學習教程】(5)資料包(The Data Package)

來源:互聯網
上載者:User

標籤:extjs4   javascript   proxy   data   

周邦濤(Timen)
Email:[email protected]
轉載請註明出處:  http://blog.csdn.net/zhoubangtao/article/details/27707361
1. 簡介

資料包主要負責載入和儲存你應用程式的所有資料,它包含41個類,但是其中三個是最重要的—— Model,Store和Ext.data.proxy.Proxy。這三個類幾乎在每個應用程式都有使用,並且有很多衛星類作支援。


2. Model和Store

data包的核心是Ext.data.Model。一個Model代表了一些資料的類型 —— 例如一個電子商務可能Users,Products和Orders模型。最簡單的說,一個Model就是一個欄位和資料的集合。現在來看看一個Model類的4個主要部分 —— Field,Proxy,Association和Validation。


讓我們看看怎麼建立一個Model:

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

Model通常和Store一起使用,Store就是Model執行個體的集合。建立一個Store並且載入它的資料很簡單:

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

我們來給我們的Store配置一個Ajax Proxy,告訴它載入資料url以及解析資料的Reader。這個例子中,我們的伺服器返回的是JSON,所以我們需要設定一個Json Reader去讀取回複。Store自動從users.json。users.json url應該返回一個像下邊的JSON字串:

{    success: true,    users: [        { id: 1, name: 'Ed' },        { id: 2, name: 'Tommy' }    ]}
3 內部資料

Store也可以從內部載入資料。在內部,Store將每一個傳過去的對象轉換成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' }    ]});
4. 排序和分組

Store可以執行排序、過濾和本地分組,以及支援遠程排序、過濾和分組:

Ext.create('Ext.data.Store', {    model: 'User',    sorters: ['name', 'id'],    filters: {        property: 'name',        value   : 'Ed'    },    groupField: 'age',    groupDir: 'DESC'});

在我們剛剛建立的Store中,資料會先以name,然後以id排序;並且被過濾到只剩下name包含‘Ed’的使用者,並且資料會以age做降序分組。可以通過Store的API在任意時間方便的改變排序、過濾和分組。

5. 代理(Proxy)

Store採用Proxy控制Model資料的載入和儲存。有兩種類型的Proxy:Client和Server。Client的例子是儲存資料到瀏覽器記憶體的Memory Proxy和使用HTML5本機存放區特性的Local Storage Proxy。Server Proxy處理遠程服務的資料解碼,它的例子有Ajax Proxy,JsonP Proxy以及Rest Proxy。

Proxy可以直接定義在一個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 ProxyExt.create('Ext.data.Store', {    model: 'User'});

這有兩點好處。第一,每一個使用User Model的Store將會以同樣的方式載入它所需要的資料,所以避免了為每一個Store重複定義Proxy。第二,我們能夠不通過Store載入和儲存Model資料。

data without a Store:// Gives us a reference to the User classvar 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 /usersed.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'));    }});

還有一些使用HTML5新特性的Proxy —— LocalStorage和SessionStorage。儘管較早的瀏覽器並不支援這些新的HTML5 API,它們是如此的有用,一大部分應用程式將會因它們的存在而受益。

6. 關聯

Model能夠採用Associations API關聯在一起。大多說應用程式處理各種各樣的Model,並且這些Model還總是相關聯。一個部落格應用可能有User、Post和Comment Model。每一個User建立多個Post,每個Post又接受多個Comment。看看我們是怎麼用Association來寫它們的模型的。

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'});

在你的應用中表述不同Model之間的關係很輕鬆。每一個Model可以包含和其他Model的任意數量的關聯關係,並且你的Model可以以任意順序定義。一旦我們有了一個Model執行個體,我們就可以通過它訪問它關聯的資料 —— 例如,如果想把一個給定使用者的所有Post的所有Comment列印成日誌,我們可以這麼做:

// Loads User with ID 1 and related posts and comments using User's ProxyUser.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'));            });        });    }});

上面我們建立的每一個hasMany關聯都會產生一個新函數並加入到這個Model中。我們定義每個User 模型 hasMany Post,這就在User Model中添加一個posts()方法。調用user.posts()會返回一個配置了Post Model的Store。相應的,Post Model會有一個comments()方法,因為我們給它配置了hasMany Comment。

Association不只有助於載入資料,它還有助於建立新紀錄:

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();

這裡我們執行個體化一個Post,它的user_id欄位會被自動府城User的id。調用sync()會通過配置給它的Proxy儲存這個新的Post —— 這還是一個非同步作業,如果你想當這個操作完成時受到通知,你可以給它傳入一個Callback函數。

belongsTo關聯也會在Model上產生新方法,看看我們怎麼使用:

// get the user reference from the post's belongsTo associationpost.getUser(function(user) {    console.log('Just got the user reference from the post: ' + user.get('name'))});// try to change the post's userpost.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');        }    }});

這裡的載入函數(也就是getUser)也是非同步,你也可一個傳入一個Callback函數。setUser方法簡單地更新外鍵(foreign_key,也就這裡的user_id)為100,然後儲存Post模型,同樣,穿進去的Callback函數將會在儲存操作完成(無論成功或失敗)時被觸發。

7. 載入嵌套資料

你可能會質疑,為什麼我們給User.load傳入一個success函數,但是當我們訪問User的post和comment時卻不必如此?!那是因為上邊的例子我們假設當發起一個擷取User的請求時,伺服器返回了User資料以及它說關聯的Post和Comment資料。通過上邊的關聯設定,架構會自動解析單個請求中的嵌套資料。為避免為一個User資料發一個請求,然後請求他的所有的Post資料,之後在為每一個Post載入器Comment資料,我們可以直接讓伺服器返回以上所有的資料:

{    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'                        }                    ]                }            ]        }    ]}
8. 驗證

對資料的驗證使得Ext JS 4 的模型更加豐富。為了證明,我們基於上邊講解關聯的例子做進一步改進。首先向User模型添加一些驗證:

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: ...});

驗證的格式定義和欄位的相同。在上邊的每個例子中,我們為驗證指定一個欄位和類型。上邊例子中的驗證意思是name欄位必須存在,且至少有5個字元,age欄位是個數字,gender欄位要麼是“male”,要麼是“female”,username可以是除了“admin”之外的任何值。一些驗證還需要其他的額外配置,例如length驗證需要min和max屬性,format驗證需要matcher,等等。Ext JS 4 有5種內建的驗證方式,並且添加定製化的驗證規則也很簡單。下邊看一下這些內建的驗證方式:

  • presence: 確保欄位有值。零算作有效值,但是Null 字元串不算
  • length: 確保字串長度在min和max之間。這兩個都是可選的。
  • format: 確保一個字串匹配一個Regex。上邊的例子意思是確保一個欄位是由4個數字後跟至少一個字元組成。
  • inclusion: 確保一個值位於一個指定的集合中(例如,確保性別是male或者female)
  • exclusion: 確保一個值不在一個指定的集合中(例如黑名單使用者名稱,像’admin‘)

現在我們對不能的驗證做什麼事情有一個瞭解了,讓我們在一個User執行個體上使用一下。首先建立一個user,然後運行驗證方法,注意出現的錯誤:

// now lets try to create a new user with as many validation errors as we canvar newUser = Ext.create('User', {    name: 'admin',    age: 'twenty-nine',    gender: 'not a valid gender'});// run some validation on the new user we just createdvar errors = newUser.validate();console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errorsconsole.log('All Errors:', errors.items); //returns the array of all errors found on this model instanceconsole.log('Age Errors:', errors.getByField('age')); //returns the errors for the age field

這裡的關鍵函數式validate(),它運行所有配置的驗證,然後返回一個Errors對象。Errors對象包含任何發現的錯誤的集合,再加上一些方便的方法,例如isValid(),如果在任何欄位上都沒有錯誤,它會返回true,以及getByField()方法,它會返回一個給定欄位上出現的所有錯誤。

9. 總結

本章主要講述了Ext JS 4的Data包中的主要功能,從Model、Store、Proxy以及Model的關聯以及驗證等方面做了詳細介紹。通過本文的學習,你能都Ext JS 4的資料操作和互動有一個初步的認識。

10. 參考資料
  1. http://dev.sencha.com/deploy/ext-4.1.0-gpl/docs/index.html#!/guide/data

周邦濤(Timen)
Email:[email protected]
轉載請註明出處:  http://blog.csdn.net/zhoubangtao/article/details/27707361

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.