Ext JS 教程-ExtJS 4中的數據包(Package)
小編:管理員 389閱讀 2022.09.07
數據包(data package)是用來加載和保存你應用程序中的數據的東西,包含41個類,但是其中有三個類比所有其他類更加重要——Model,Store和Ext.data.proxy.Proxy。這些類被幾乎所有的應用程序用到了,并且受到了許多其他衛星類(satellite class)的支持。
Models 和 Stores
數據包的中心是 Ext.data.Model。一個Model在一個應用程序中展現一些類型的數據 —— 例如一個commerce應用也許會有用戶、產品和訂單的模型。把它看得簡單點一個模型就是屬性域和它們的數據的集合。下面我們來看看Model中四個重要的部分 —— 屬性與Field,代理Proxy,關聯Association 和 驗證Validation。
現在讓我們來看看如何創建一個模型:
Ext.define('User', { extend: 'Ext.data.Model', fields: [ { name: 'id', type: 'int' }, { name: 'name', type: 'string' } ] });復制
模型典型的被使用于一個 存儲(Store),它基本上就是一個模型實體的集合。設置一個存儲并且加載它的數據是簡單那的:
Ext.create('Ext.data.Store', { model: 'User', proxy: { type: 'ajax', url : 'users.json', reader: 'json' }, autoLoad: true });復制
我們使用了一個Ajax代理來設置我們的存儲,告訴它數據加載的url來源還有解碼數據的閱讀器(Reader)。在這種情況下,服務器會返回JSON,因此我們設置了一個Json閱讀器去讀取回應(response)。存儲自動加載users.json這個url中的User模型實體的集合。users.json的url應該返回一個像下面這樣的JSON字符串:
{ success: true, users: [ { id: 1, name: 'Ed' }, { id: 2, name: 'Tommy' } ] }復制
見Simple Store實例是一個生動的demo。
內聯數據
存儲也可以加載內聯數據。本質上,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' } ] }); 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’的用戶,并且數據會根據年齡按降序分組排列。在任何時候使用存儲的API進行排序,過濾盒分組都是容易的。見Sorting Grouping Filtering 實例是一個生動的demo。
代理
代理被存儲用來控制加載和保存模型的數據。有兩種類型的代理:客戶端的和服務器端的?蛻舳说拇韺嵗ㄔ跒g覽器的內存中存儲數據的Memory和在可用的時候使用HTML5本地存儲(local storage)特性的LocalStorage。服務器上的代理把分組的數據處理到遠程的服務器上,示例包括 Ajax,JsonP 和 Rest。
代理可以像這樣直接定義在一個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' });復制
這通過兩種方式幫助了我們。首先,貌似每一個使用這個User模型的Store都將需要用同樣的方式加載它們的數據,因此我們避免了為每一個Store都重新定義代理。第二,我們現在可以不用Store就加載和保存模型數據了。
// 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')); } });復制
也有利用了新式的HTML5的能力——LocalStorage和SessionStorage的代理。盡管老一點的瀏覽器不支持這些新的HTML5標簽,由于大量的應用程序將會受益于它們的表現,還是很有用的。
關聯(Association)
Model可以使用Association API鏈接起來。大部分應用程序需要處理不懂的模型,并且這些模型幾乎都總是有關聯的。一個博客創作應用程序也許會有User,Post和Comment模型。每一個User創建了Post,并且每一個Post接收Comment。我們可以像這樣表示那些關系:
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' });復制
在你的應用程序中表示不同的模型之間的豐富管理是很簡單的一件事。每一個模型能夠擁有任何數量的與其它模型的關聯,并且你的模型可以以任何順序被定義。一旦我們有了一個模型實體,我們就能夠很容易的橫掃這些關聯的數據——舉個例子,如果我們想記錄一個User的每一個Post的所有Comment,我們可以像下面這樣做:
// 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')); }); }); } });復制
每一個我們創建于一個新的函數的結果之上的hasMany關聯被添加到模型中。我們聲明了每一個User模型有許多(hasMany)Post,在上面的一小段中就添加了user.posts() 函數。調用user.posts() 返回一個配置為Post模型的存儲。同樣的,Post模型獲得了一個comments()函數,因為我們有有許多(hasMany)Comment 關聯的設置。
關聯不僅僅對于加載數據有幫助——它們對于創建新的記錄也很有用:
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的user_id域中的id。調用sync()通過它配置的代理保存了這個新的Post —— 這里再次是一個傳入一個你想在操作完成時通知到的回調的同步操作。
belongsTo關聯也會在模型中生成新的方法。這里我們可以像那樣使用:
// 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 use 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)是異步的并且需要一個回調函數去獲取一個用戶的實體。setUser方法簡單的更新并保存了Post模型的外鍵(這里是user_id)為100.一般的,回調能夠被傳入會在操作完成時被觸發的東西里面——不管是成功與否。
加載嵌套的(Nested)數據
你可能會想到為什么我們認為在User.load調用中傳入了一個success函數,但是沒有在訪問User的posts和comments函數也同樣這么做。這是因為上面的例子假設當我們做一次獲取所有用戶的請求時服務器返回用戶數據,附帶返回它所有內嵌的Post和Comments。通過像我們上面那樣設置關聯,框架能夠自動的在一個單獨的請求中轉出內嵌的數據。而不是為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' } ] } ] } ] }復制
數據全是由框架自動轉出的。配置你模型的代理在任何地方加載數據是很容易的,并且他們的閱讀器可以處理任何回應(response)形式。使用ExtJS 3,模型和存儲在框架的許多的組件如Grid,Tree和Form被用到。
可以工作的模型使用關聯的例子,見Associations and Validations。
淡然,以無內嵌的方式加載你的數據也是可能的。如果你需要僅在必要時“懶加載”關聯的數據,這會是很有用的。讓我像以前以前只加載User的數據,除了我們假定回應只包含User數據,沒有任何關聯的Post。然后我們向我們的回調中添加一個user.Post().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')); }); }); } }); } });復制
完整的示例見 Lazy Associations。
驗證(Validations)
隨著對數據的驗證支持,ExtJS 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”意外可以是任何東西。一些驗證使用附加的配置的選項——例如長度驗證可以使用min和max屬性,格式可以使用一個matcher,等等。ExtJS中有五種驗證,并且添加定制的規則也是容易的。首先,讓我恩看看內置的這些:
presence:簡單的確保值域有一個值。零算做事一個值,但是字符串不算。
length:確保一個字符串在一個最小和最大的長度之間,兩個限制都是可選的。
format:確保一個字符串符合一個正則表達式描述的格式。在上面的實例中我們確保了age值域只包含數字。
inclusion:確保一個值在一個特定的值的集合之中(比如:確保性別不是男就是女)。
exclusion:確保一個值不在一個特定的值的集合之中(比如:黑名單中的“admin”)。
現在我們已經掌握了不同的驗證做些什么,讓我們試試針對一個User實體使用它們。我們將會創建一個用戶并且針對它運行驗證,注意任何驗證失。
// 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復制
這里關鍵的函數是validate(),它運行所有配置好的驗證并且返回Error對象。這個簡單的對象只是一個任何被發現的驗證錯誤的集合,加上一些便利的函數比如 isValid() —— 如果任何值域都沒有錯誤,它就返回true——還有 getByField(),它返回一個指定值域的所有驗證錯誤。
完整的使用驗證的實例,見Associations and Validations。
---------------
相關推薦
- ExtJs七(ExtJs Mvc創建ViewPort) 前言在4.1的時候,要先創建一個擴展于Ext.app.Application的類,然后用create創建它的實例來開始應用程序的。而在4.1.1,則可直接調用application方法開始執行應用程序,簡化了。調用application方法,其參數是一個配置對象,主要配置項有以下三個:name:用來…
- Hibernate Criterion 在查詢方法設計上能夠靈活的依據Criteria的特點來方便地進行查詢條件的組裝.Hibernate設計了CriteriaSpecification作為Criteria的父接口,以下提供了Criteria和DetachedCriteria.Criteria和DetachedCriteria的主要差別在于創建的形式不一樣,Criteria是在線的,所…