ExtJs4學習(八)數據代理Proxy


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


這里出現了兩個額外的參數 - modelreader. 這些參數在通過Store來創建proxy實例時是默認指定的 - Store中已經定義了 Model,並且Proxy的默認ReaderJsonReader.

最后我們調用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 - 控制如何向服務器發送頁數(同樣參見startParamlimitParam)
  • 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;=25
AjaxProxy還會向服務器發送排序和過濾信息. 讓我們來看看如何使用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);
	}
);



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM