ExtJs數據代理我們介紹常用的四種,但會着重介紹ajax代理,因為日常開發中,這個最為常用
Ext.data.proxy.Ajax
AjaxProxy(Ajax數據代理類)是你的應用程序中使用最廣泛的獲取數據的方式. 它使用AJAX請求來從服務器獲取數據, 然后通常將它們放入 Store中. 讓我們來看一個典型的配置. 這里我們為一個Store設置一個AjaxProxy代理. 首先我們准備好一個 Model:
Ext.define('User', { extend: 'Ext.data.Model', fields: ['id', 'name', 'email'] }); //一個包含AjaxProxy代理的Store, 使用參數方式綁定. var store = Ext.create('Ext.data.Store', { model: 'User', proxy: { type: 'ajax', url : 'users.json' } }); store.load(); store.on('load',function(store,records){ store.each(function(record){ console.log(record.get('name')); }); })這里說明下官網的例子是直接使用store.each 方法 ,但那是沒用的
store 中each()方法的使用應在load完使用,確切的說應該在on('load')事件中使用,切記
我們的例子將會把user數據加載到Store中, 首先我們定義一個Model, Model包含的字段(fields)即為從服務器返回 數據的相應字段. 接下來我們定義一個Store, 它包含了一個proxy配置項. 此配置項將會自動轉換為一個 Ext.data.proxy.Ajax類的實例, 此實例包含了我們定義的url參數. 這等效於下面這段代碼
new Ext.data.proxy.Ajax({ url: 'users.json', model: 'User', reader: 'json' });
這里出現了兩個額外的參數 - model和reader. 這些參數在通過Store來創建proxy實例時是默認指定的 - Store中已經定義了 Model,並且Proxy的默認Reader為JsonReader.
最后我們調用store.load(), 觸發執行AjaxProxy的action, 向配置的url發送請求(本示例為'users.json'). 由於我們執行的是數據讀取, 所以講發送一個GET方式的請求.(請求方式的定義參見actionMethods - 默認所有讀數據請求(read)的方式為GET, 而所有寫請求(create、update、destroy)的方式為POST)
配置項
actionMethods: { create : 'POST', read : 'GET', update : 'POST', destroy: 'POST' }
限制
AjaxProxy無法跨域獲取數據. 例如你的程序地址為http://domainA.com, 那么你就無法從http://domainB.com獲取數據. 這是因為瀏覽器都有 一個內置的安全機制來阻止AJAX的跨域請求.
如果你需求從其他域名地址獲取數據, 並且你無法從服務器端設置代理(某些運行在你自己服務器端的程序, 用來將請求轉發給http://domainB.com, 但客戶端看來數據還是來自http://domainA.com), 你可以使用Ext.data.proxy.JsonP代理和JSON-P技術, 這樣只要http://domainB.com 上的服務器支持JSON-P響應, 就能夠解決你的跨域請求問題.
配置Reader和Writer
AjaxProxy可以配置任意類型的Reader來解讀服務器端的響應. 如果不顯式指定Reader, 將默認使用 JsonReader. 可以使用簡單屬性對象的方式來配置Reader, 代理將自動將其轉換為Reader類的實例:
var proxy = new Ext.data.proxy.Ajax({ model: 'User', reader: { type: 'xml', root: 'users' } }); proxy.getReader(); //返回一個XmlReader的實例.
生成Url
AjaxProxy會自動將排序,過濾,翻頁和分組參數添加到生成的url中. 可以使用下面這些屬性來配置這些參數:
- pageParam - 控制如何向服務器發送頁數(同樣參見startParam和limitParam)
- sortParam - 控制如何向服務器發送排序信息
- groupParam - 控制如何向服務器發送分組信息
- filterParam - 控制如何向服務器發送過濾信息
每個AjaxProxy發出的請求對象由一個Operation對象來描述. 為了說明我們是如何生成自定義url的, 讓我們 看看下面這個Operation:
var operation = new Ext.data.Operation({ action: 'read', page : 2 });
然后我們用此Operation來發布請求, 通過調用 read :
var proxy = new Ext.data.proxy.Ajax({ url: '/users' }); proxy.read(operation); //GET /users?page=2
很簡單吧 - Proxy代理類只需要復制Operation中的page值即可. 我們還能自定義如何向服務器發送page數據:
var proxy = new Ext.data.proxy.Ajax({ url: '/users', pageParam: 'pageNumber', //默認page }); proxy.read(operation); //GET /users?pageNumber=2
還有另一個方案, 可以配置Operation來發送start和limit參數代替page:
var operation = new Ext.data.Operation({ action: 'read', start : 50, limit : 25 }); var proxy = new Ext.data.proxy.Ajax({ url: '/users' }); proxy.read(operation); //GET /users?start=50&limit;=25同樣地我們可以自定義startParam limitParam
var proxy = new Ext.data.proxy.Ajax({ url: '/users', startParam: 'startIndex',//默認start limitParam: 'pageSize'//默認limit }); proxy.read(operation); //GET /users?startIndex=50&pageSize;=25AjaxProxy還會向服務器發送排序和過濾信息. 讓我們來看看如何使用Operation來表示:
var operation = new Ext.data.Operation({ action: 'read', sorters: [ new Ext.util.Sorter({ property : 'name', direction: 'ASC' }), new Ext.util.Sorter({ property : 'age', direction: 'DESC' }) ], filters: [ new Ext.util.Filter({ property: 'eyeColor', value : 'brown' }) ] });當使用一個包含sorters和filters參數的 Store 來加載數據時, 就會在內部生成上面這樣的對象. 默認情況下, AjaxProxy 會對sorters和filters進行JSON轉換, 從而得到如下結果(注意url發送前會被加密, 這里為便於閱讀使用未加密的串):
var proxy = new Ext.data.proxy.Ajax({ url: '/users' }); proxy.read(operation); //GET /users?sort=[{"property":"name","direction":"ASC"},{"property":"age","direction":"DESC"}]&filter;=[{"property":"eyeColor","value":"brown"}]同樣地我們能夠自定義這些參數項. 假設我們的服務器讀取排序信息的格式是"sortBy=name#ASC,age#DESC". 我們可以像這樣配置AjaxProxy來提供這種格式:
var proxy = new Ext.data.proxy.Ajax({ url: '/users', sortParam: 'sortBy', filterParam: 'filterBy', //我們自定義實現排序信息轉碼方法 - 將sorters轉換為"name#ASC,age#DESC" encodeSorters: function(sorters) { var length = sorters.length, sortStrs = [], sorter, i; for (i = 0; i < length; i++) { sorter = sorters[i]; sortStrs[i] = sorter.property + '#' + sorter.direction } return sortStrs.join(","); } }); proxy.read(operation); //GET /users?sortBy=name#ASC,age#DESC&filterBy;=[{"property":"eyeColor","value":"brown"}]同樣我們還能夠通過自定義實現 encodeFilters 方法來對filters信息進行轉碼
Ext.data.proxy.JsonP
JsonP代理用在當你想從你自己的應用服務器以外的域名加載數據時(跨域調用). 比如你的應用運行在http://domainA.com上, 那么就無法通過 Ajax從http://domainB.com加載數據, 因為瀏覽器不允許跨域的ajax請求.
而通過JsonP代理我們可以擺脫這個限制. 每當進行AJAX請求時, JsonP代理就在DOM中注入一個<script>
標簽. 比如我們想從http://domainB.com/users 這個url下加載數據, 那么就會注入一個如下的script標簽:
<script src="http://domainB.com/users?callback=someCallback"></script>在我們注入了上面這個標簽后, 瀏覽器就會向這個url發送一個請求. 通過url中的callback, 我們通知domainB的服務器: 當結果返回時請調用 此回調函數並傳入返回的數據. 只要服務器將響應結果組成如下格式, 調用就成功了:
Ext.regModel("User",{ fields:[ {name:'name',type:'string'} ], proxy:{ type:'jsonp',//跨域交互的代理 url:'http://www.uspcat.com/extjs/person.php' } }); var person = Ext.ModelManager.getModel('User'); person.load(1,{ scope:this, success:function(model){ alert(model.get('name')); } });
Ext.data.proxy.LocalStorage
LocalStorageProxy使用最新的HTML5本地數據庫API, 將Model數據保存在本地客戶端. HTML5本地數據庫是一個 鍵值對存儲(例如 不能存儲像JSON這樣的復雜對象), 因此LocalStorageProxy在保存和讀取數據時, 自動進行序列化和反序列化.
本地數據庫在保存用戶個人信息時非常有用, 從而不再需要在服務端建立數據結構.
Ext.define('User', { fields: ['id', 'name'], extend: 'Ext.data.Model', proxy: { type: 'localstorage' } });
var store = new Ext.data.Store({ model:'User' }); store.add({name:'somnus'}); // 保存數據 store.sync(); // 讀取數據 store.load(); store.each(function(record){ console.info(record.get('name')); });
Ext.data.proxy.Memory
內存代理. 此代理使用簡單的本地變量進行數據的存儲/讀取, 所以其內容將在每次頁面刷新時被清除.
通常此代理並不直接使用, 而是作為Store的輔助服務對象, 為其在加載數據時提供reader對象. 例如, 假設我們有一個 User Model和Store, 以及一些我們想要加載的內部數據, 但是這些數據的格式並不是很合適: 這時我們就可以用一個帶有JsonReader的MemoryProxy 來為Store讀取這些數據:
//我們將在store中使用的model對象 Ext.define('User', { extend: 'Ext.data.Model', fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'}, {name: 'phone', type: 'string', mapping: 'phoneNumber'} ] }); //數據字段不是按照model中定義排列的 - 字段'phone'在此稱為'phoneNumber' var data = { users: [ { id: 1, name: 'Ed Spencer', phoneNumber: '555 1234' }, { id: 2, name: 'Abe Elias', phoneNumber: '666 1234' } ] }; //請注意我們是如何通過設置reader的'root'來滿足上面的數據結構的. var store = Ext.create('Ext.data.Store', { autoLoad: true, model: 'User', data : data, proxy: { type: 'memory', reader: { type: 'json', root: 'users' } } });
var memoryProxy = Ext.create("Ext.data.proxy.Memory",{ data:data, model:'User' }) data.push({name:'sunday',age:1}); memoryProxy.update( new Ext.data.Operation( { action:'update', data:data }), function(result){}, this ); memoryProxy.read( new Ext.data.Operation(), function(result){ var datas = result.resultSet.records; Ext.each(datas,function(model){ console.info(model.get('name')); }); var totalRecords = result.resultSet.total; alert('讀取內存數據,記錄總是:' + totalRecords); } );