javascript
ExtJS4 API文档阅读(四)——Data
2019獨角獸企業重金招聘Python工程師標準>>>
ExtJS4 API文檔閱讀(四)——Data
數據
Data包負責加載和保存你應用程序中的所有數據,由41個類構成,其中有三個類是最重要的,分別是模型類(Model),存儲類(Store),代理類(Ext.data.proxy.Proxy)。它們幾乎在每個應用程序中都被使用到,并且有很多相附類為它們提供支持。
模型類和存儲類
模型類(Ext.data.Model)是data包的核心部件。每個模型代表應用程序中的一些數據類型-例如一個電子商務應用程序可以有Users、Products、Orders等模型類。簡單來說,模型僅僅是一些域和每個域對應數據的集合。我們將重點研究模型類中的四個主要部分—域(Fields)、代理(Proxies)、關聯(Associations)和驗證(Validations)。
現在讓我們看看如何創建一個模型類:
Ext.define('User', {extend: 'Ext.data.Model',fields: [{ name: 'id', type: 'int' },{ name: 'name', type: 'string' }] });
模型類通常在存儲類中使用,這些存儲類主要是一些模型實例的集合。設置存儲類和加載它的數據是很簡單的:
Ext.create('Ext.data.Store', {model: 'User',proxy: {type: 'ajax',url : 'users.json',reader: 'json'},autoLoad: true });
我們用Ajax代理(?Ajax Proxy)配置我們的存儲類,告訴它加載數據的url地址和用來解碼數據的讀取器(Reader)。這樣,我們的服務器將返回JSON格式的數據,我們可以使用設置的Json讀取器(Json Reader)來解析響應。上面創建的存儲類實例從url地址users.json中自動加載一系列User模型類實例的數據。
users.json應該返回如下所示的JSON字符串:
{success: true,users: [{ id: 1, name: 'Ed' },{ id: 2, name: 'Tommy' }] }
請查看Simple Store獲取一個演示實例。
內聯數據
存儲類實例也可以加載內聯數據,它們轉換每個傳遞進data中的對象為模型類實例:
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)
排序和分組
存儲類實例能在本地執行排序、過濾和分組,同樣也提供遠程排序、過濾和分組:
Ext.create('Ext.data.Store', {model: 'User',sorters: ['name', 'id'],filters: {property: 'name',value : 'Ed'},groupField: 'age',groupDir: 'DESC' });
我們剛剛創建的存儲類實例中,數據首先將按照name排序,其次按id排序;并且數據將被過濾為僅包含name為’Ed’的Users,然后數據將按年齡進行分組且遵循由小到大的順序。任何時候調用存儲類的API進行排序、過濾和分組都是是很輕松的。查看排序、分組、過濾存儲類實例(Sorting Grouping Filtering Store)獲取一個演示示例。
代理
代理類被存儲類使用以便于管理加載和保存模型類數據。有兩種類型的代理:客戶端代理(Client)和服務器端代理(Server)。客戶端代理包括存儲數據在瀏覽器內存的內存方式(Memory)和使用HTML5本地存儲器(可用時)的本地存儲方式(Local Storage)。服務器端代理操作一些從遠程服務器調度來的數據,例如包括Ajax,Jsonp和Rest方式。
代理方式可以直接在模型類中定義,如下:
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' });
這對我們有兩方面的好處:首先,使得每個使用User模型類的存儲類實例以相同方式加載數據變得可行,這樣我們避免了必須為每個存儲類實例復制相同代理方式的定義。其次,現在我們可以不必使用存儲類來加載和保存模型數據:
// Gives us a reference to the User class // 創建一個User類的引用 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 //我們可以直接保存ed而不用先把它添加到一個存儲類中,因為我們配置了 // configured a RestProxy this will automatically send a POST request to the url /users //一個能自動發送一個POST請求到指定url的Rest代理 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 1并對其一些相關操作(執行一個GET請求到 /users/1) User.load(1, {success: function(user) {console.log("Loaded user 1: " + user.get('name'));} });
也有利用HTML5新功能--?LocalStorage和?SessionStorage?–?的代理模式。盡管舊的瀏覽器不支持這些新的HTML5 APIs,它們仍然是有用的,因為很多應用程序將從這些新特性的存在中受益。
直接在模型類中使用代理的例子(Example of a Model that uses a Proxy directly)
關聯
模型類之間可以通過關聯API鏈接在一起。大多數應用程序需要處理很多不同的模型類,并且這些模型類之間通常是相關聯的。例如一個博客寫作應用程序可能有User(用戶)、Post(文章)、Comment(評論)等模型類。每個用戶(User)可以創建多篇文章(Posts),并且每篇文章接受很多評論(Comments)。我們可以如下表示這些關系:
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' });
這將使得在你的應用程序中表示這種復雜關系變得簡單。?每個模型類可以和其他模型類有任意多的關聯,并且你的模型類可以按任意順序定義。一旦我們創建了一個模型類實例,我們可以很輕松地遍歷與其相關聯的數據?--?例如,如果我們想記錄一個給定用戶的每篇文章的所有相關評論,我們可以如下這樣操作:
// Loads User with ID 1 and related posts and comments using User's Proxy //加載User使用ID 1和相關的文章和評論使用User的代理 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'));});});} });
上例我們創建每一個的hasMany關聯將產生一個新方法添加到這個模型類上。我們聲明的每個User模型類實例有許多(hasMany)文章(Posts),這將為我們添加user.posts()方法,如上面代碼段中使用的那樣。調用user.posts()方法將返回一個配置了Post模型的存儲類實例。依次類推,Post模型實例獲取了一個comments()方法,因為我們為其設置了hasMany?評論關聯。關聯不僅對加載數據來說是有用的,而且對創建新記錄也是有用的:
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賦值給Post中的user_id字段。調用sync()方法,將通過配置的代理方式來保存新創建的Post模型類實例?–?再者,如果你想讓操作完成時得到反饋,你可以調用異步操作并傳遞進一個回調函數來實現。屬于(belongsTo)關聯也能在模型類實例中生成一個新方法,如我們下面介紹的這個示例:
// get the user reference from the post's belongsTo association //得到user實例引用從post實例的belongsTo關聯配置 post.getUser(function(user) {console.log('Just got the user reference from the post: ' + user.get('name')) }); // try to change the post's user //嘗試改變文章的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');}} });
再次說明,加載函數(getUser)是異步調用的,并且需要一個回調函數作為參數來獲得user實例。setUser方法僅更新外鍵(本例中的user_id字段)的值為100,并保存這個Post模型類實例。通常,不管成功與否,當保存操作完成時,傳遞進去的回調函數都將被觸發。
加載內嵌的數據
你或許想知道為什么調用User.load方法時,我們傳遞一個success方法,但當訪問User的文章(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'}]}]}] }
這些數據將被框架自動解析出來。配置模型類的代理方式以用來加載任何地方的數據會變得很輕松,并且它們的閱讀器模式幾乎可以處理任何格式的響應數據。和Ext JS 3一樣,模型類和存儲類在整個框架中被許多組件使用,例如表格,樹,表單。
查看關聯和驗證(Associations and Validations)的演示示例以獲取一個可實際操作并且具有關聯關系的模型實例。
當然,你可以以一種非嵌套的方式加載你的數據。如果你僅想需要時加載相關的數據,這種“懶惰加載”模式將可能是有效地。如前所做,我們僅加載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 Proxyuser.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'));});});}});} });
查看懶惰關聯(Lazy Associations)模式可以獲取一個完整的示例
驗證
自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,并且用戶名可以為除了admin外的其他任何名稱。一些驗證器可能具有其他的可選配置?--?例如,長度驗證可以具有最大和最小屬性,格式(format)可以具有匹配(matcher)屬性等。Ext JS有五種內置的驗證器,且可以輕松地添加用戶自定義規則。首先讓我們看看這五種類型:
- 存在(presence)??確保該域必須有確定值。0被看作有效值,但空字符串將不被視為有效值。
- 長度(length)??確保一個字符串長度位于最大和最小值之間。兩個參數都是可選的。
- 格式(format)??確保一個字符串匹配指定的正則表達式。上例中我們確保age域必須為數字。
- 包含(inclusion)?確保該域的值在指定的數值集合中(例如確保性別只能是男或女)。
- 排除(exclusion)?確保該域的值不在指定的數值集合中(例如用戶名不能為admin)
既然我們已經理解了不同驗證器的功能,讓我們嘗試在一個User實例中使用它們。
我們創建一個user實例并在其中運行驗證器,注意產生的任何錯誤:
// now lets try to create a new user with as many validation errors as we can // 現在讓我們嘗試創建一個user實例,并產生盡量多的驗證錯誤 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 // 在我們剛剛創建的user實例中運行一些驗證器 var errors = newUser.validate(); console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errors 當有驗證器錯誤產生時,返回false 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返回age域產生的錯誤
這里的關鍵函數是validate(),該函數運行所有配置驗證器并返回一個Errors對象。這個簡單的對象為所有錯誤的集合,并且添加了一些便利的方法,例如isValid()?--?當任何域都沒有錯誤產生時,返回true,還有getByField()方法,返回給定域產生的所有錯誤。
請查看關聯和驗證(Associations and Validations)示例以獲取一個使用驗證器的復雜例子。
轉載于:https://my.oschina.net/yoyoko/blog/130966
總結
以上是生活随笔為你收集整理的ExtJS4 API文档阅读(四)——Data的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCPDUMP for Android(
- 下一篇: JavaScript V8引擎编译