原作者:Kris Zyp
原文連結:http://dojotoolkit.org/documentation/tutorials/1.6/store_driven_grid/
譯者:zhuxw(zhuxw1984@gmail.com)
鑒於DataGrid對於表格式資料的有效呈現,它早已成為許多應用的核心組件之一。在本教程中,我們將著眼於如何為grid連上store(Dojo的用戶端資料集——譯者注),以進行快捷高效的資料讀取和更新。
難度:初等
Dojo版本:1.6
DataGrid和Store
首先,我們將建立一個store。在本例中將建立一個JsonRest store,它將通過JSON REST HTTP成為串連grid和我們的伺服器的紐帶。建立代碼如下:
dojo.require("dojo.store.JsonRest");myStore = new dojo.store.JsonRest({target:"MyData/"});
以上代碼錶明這個store將向給定的URL("MyData/")發送請求,以擷取或修改資料。
注意:其他類型的store也能使用,例如dojo/store/Memory(原文有誤,並不存在dojo/data/Memory。 ——譯者注),也能夠驅動DataGrid。然而本教程只採用 JsonRest store。
現在我們可以建立DataGrid了。在1.6版中DataGrid仍然基於dojo.data API,因此我們將使用介面適配器dojo.data.ObjectStore來串連DataGrid和我們剛剛建立的store。DataGrid採用標準的Dojo小組件的構造方式,因此我們可以用我們的store作為參數來執行個體化一個DataGrid(同時請確保已經匯入了正確的CSS檔案(例如使用claro主題的話,可匯入dojox/grid/resources/claroGrid.css。——譯者注))
dojo.require("dojox.grid.DataGrid");dojo.require("dojo.data.ObjectStore");dojo.ready(function(){ grid = new dojox.grid.DataGrid({ store: dataStore = dojo.data.ObjectStore({objectStore: myStore}), structure: [ {name:"State Name", field:"name", width: "200px"}, {name:"Abbreviation", field:"abbreviation", width: "200px"} ] }, "target-node-id"); // make sure you have a target HTML element with this id grid.startup();});
現在我們已經建立好了grid,當它啟動完成後(即調用grid.startup()後——譯者注),將調用store的query()方法,從而觸發一個請求來擷取資料。伺服器需要返回一個包含資料的JSON數組作為響應,這樣,grid就會將這些資料渲染出來。這個JSON數組形式的響應看上去就像這樣:
[ {"id":0,"name":"Alabama","abbreviation":"AL","capital":"Montgomery"}, {"id":1,"name":"Alaska","abbreviation":"AK","capital":"Juneau"}]
【樣本】
好了,現在我們已經有了一個可以正常工作的grid,它能從我們的伺服器擷取資料。接下來我們來看一下如何增強我們這個組件。
分頁
通過響應滾動滑鼠滾輪事件來實現即時分頁是Dojo DataGrid的強大功能之一。它為瀏覽大資料集提供了無縫、直觀的使用者體驗——無需點擊任何分頁控制項,只需簡單地滾動滾輪即可看到更多資料。這種即時分頁是通過向store不斷髮送一種特殊的請求實現的,這種要求節流了每次返回的資料行數。grid將給store的query()方法傳一個請求對象作為其第二個參數,這個對象中有兩個屬性:start和count。JsonRest store通過HTTP頭部屬性Range將這兩個參數發送到伺服器端。這是一個對於延展性非常重要的特性,因為這使得我們能夠消極式載入在可視範圍之外的行,而不是一下子載入所有資料。向伺服器發出的第一個請求如下所示(你可以在瀏覽器的調試工具中方便地查看這些請求):
GET /MyData/ HTTP/1.1Range: items=0-19...
http伺服器可以通過Range頭來確定需要向用戶端發送多少行資料(例如,可以把這個Range頭轉化為MySQL伺服器的LIMIT或OFFSET參數)。對於大規模的資料集,當你將grid向下滾動時,將觸發後續的請求。這些後續請求也都具有Range參數,只不過位移量(起始行號)不同罷了。grid並不直接向伺服器發送請求,而是調用store的函數(這些都是自動完成的):
myStore.query("", {start: 0, count: 20}).then(...grid's callback...);
排序
DataGrid還支援在點擊列頭時觸發對資料排序的請求。出於效能考慮,grid將實際的排序工作交給了store去做,因為在資料庫中進行排序的效率是最高的。當點擊一列時,grid將向store發送一個帶有sort參數的新請求,這個參數通過query()方法的第二個形參(是一個參數對象)傳入。對於JsonRest store來說,這將告訴伺服器,返回的資料需要按照某個屬性排序(在本例中是“name”屬性):
GET /MyData/?sort(+name) HTTP/1.1Range: items=0-19...
grid內部通過下面的邏輯向store發出排序請求:
myStore.query("", {start: 0, count: 20, sort:[{attribute:"name"}]}). then(...grid's callback...);
grid這種與store的互動方式有一個很重要的特性,那就是這種請求資料的方式使得store的資料檢視保持獨立。這意味著如果我們在grid外直接向store請求資料,對於grid的顯示是沒有任何影響的。換句話說,grid對於store的請求只限於其自身,與其他請求是相互獨立的。你無法直接對store排序,你只能擷取一個排好序的資料檢視,這個資料檢視就是當你點擊列頭時grid顯示的內容。
過濾
除了排序視圖外,我們還可以建立過濾視圖。這可以通過setQuery()方法做到。DataGrid將把這些參數傳給store(和排序與分頁一樣,過濾資料也最好在資料庫層面完成,這樣的效率最高)。例如,過濾出所有縮寫為“NY”的行,只需要這樣寫:
grid.setQuery({abbreviation: "NY"});
這句話將觸發一個如下請求:
GET /MyData/?abbreviation=NY HTTP/1.1Range: items=0-19...
這個請求也將被轉化為合適的資料庫查詢。
在Grid內部,傳給setQuery方法的這個請求是作為store.query()方法的第一個參數。如果使用的是JsonRest store,這個請求最終會轉化為字串,接在URL後面以http GET方法的形式發送到伺服器端。
編輯Grid
DataGrid支援雙擊後(或單擊後)直接編輯儲存格,可以提供很好的使用者體驗。DataGrid通過統一的資料介面將改動寫回store。一旦編輯了一個儲存格,改變後的資料通過Dojo資料配接器的setValue方法寫回,在未儲存之前暫時留在適配器中,直到調用了save()方法:
dataStore.save();
調用save()方法後,所有未儲存的改動都會通過put()方法儲存到store中。
注意:DataGrid經常需要通過ID擷取對象。為了避免向伺服器發送多餘的請求,還可以為store加上一層Cache緩衝,從而在本地快速存取緩衝的對象:
dojo.require("dojo.store.JsonRest");dojo.require("dojo.store.Memory");dojo.require("dojo.store.Cache");myStore = dojo.store.Cache( dojo.store.JsonRest({target:"MyData/"}), dojo.store.Memory());
結論
DataGrid是一個功能強大、豐富的表格控制項,提供伸縮式的表格式資料渲染,還包括排序、過濾、列移動、選擇、編輯、鍵盤導航等等。DataGrid與store的緊密聯絡使得在Grid中對資料處理進行配置非常容易。