原作者:Bryan Forbes
原文連結:http://dojotoolkit.org/documentation/tutorials/1.6/datagrid/
譯者:zhuxw (zhuxw1984@gmail.com)
鑒於DataGrid對於表格式資料的有效呈現,它早已成為許多應用的核心組件之一。在本教程中,我們將著眼於如何定義grid的布局結構,並討論DataGrid所採用的滾屏機制。
難度:中等
適用Dojo版本:1.6 (其實絕大部分內容自1.2開始就支援了——譯者注)
dojox.grid.DataGrid
估計我們都有過這樣的經曆:你的老闆突然找到你,要求在你那個正在開發的應用中顯示一大堆資料。作為一個Web開發人員,你知道資料呈現得越多,瀏覽器佔用的記憶體就越大——但你的老闆不懂這個,他只是要把這些資料弄進那個應用裡。現在就是dojo的dojox.grid.DataGrid大顯身手的時候了。DataGrid能夠承載數千行的資料,並自如地滾屏,同時只佔用相當小的記憶體。在本教程中,我們將學習DataGrid的基礎知識。
為了提供DataGrid處理海量資料能力的直觀印象,我們建立了一個顯示美國職業棒球選手統計資料的grid:
【樣本】
可以看到,DataGrid能夠輕易地承載這份包含了17452項紀錄的資料列表。在本教程中,我們將使用一份較小的資料集作為例子:只顯示名人堂球員的擊球統計。好了,讓我們開始吧!
DataGrid的組成部分
你可能已經猜到了,DataGrid由數個不同部分組成。在最頂層,一個DataGrid由視圖(View)組成。視圖將DataGrid分割成好幾個地區,並為每個地區單獨渲染表頭(header)和內容(content)。表頭和內容由行(row)組成,行由子行(sub-row)組成。子行由儲存格(cell)組成。讓我們來看一些圖,好有個直觀的理解:
在後面的教程中,我們還將不斷修這個樣本的布局結構。要定義一個DataGrid的模樣,我們需要在建構函式裡給structure(結構)屬性傳遞一些對象和數組。我們將從最小的可定義單元開始——儲存格——直到最大的組成部分——視圖。我們暫時不涉及如何從伺服器端擷取資料,但下一篇教程會涵蓋這部分內容。
儲存格
我們需要做的第一件事就是告訴DataGrid需要為每條資料記錄顯示哪些儲存格(或稱為“列”)。為了做到這點,我們將給structure屬性傳遞一個“儲存格定義”的數組。每一個儲存格定義對象可以包含以下幾個屬性:
- name:在表頭部分顯示的字串
- field:在資料記錄中(用於擷取資料——譯者注)的欄位名
- width:表示列寬的CSS寬度字串(需要帶單位,不帶單位的話預設為em——譯者注)
- hidden:一個布爾值,如果是true,那麼該列將被隱藏
grid = new dojox.grid.DataGrid({ store: store, query: { id: "*" }, structure: [ { name: "First Name", field: "first", width: "84px" }, { name: "Last Name", field: "last", width: "84px" }, { name: "Bats", field: "bats", width: "70px" }, { name: "Throws", field: "throws", width: "70px" }, { name: "G", field: "totalG", width: "60px" }, { name: "AB", field: "totalAB", width: "60px" }, { name: "Games as Batter", field: "totalGAB", width: "120px" }, { name: "R", field: "totalR", width: "60px" }, { name: "RBI", field: "totalRBI", width: "60px" }, { name: "BB", field: "totalBB", width: "60px" }, { name: "K", field: "totalK", width: "60px" }, { name: "H", field: "totalH", width: "60px" }, { name: "2B", field: "total2B", width: "60px" }, { name: "3B", field: "total3B", width: "60px" }, { name: "HR", field: "totalHR", width: "60px" } ]}, "grid");
【樣本】
DataGrid還提供了通過CSS樣式和CSS類控制儲存格視覺效果的方法。儲存格定義中的headerStyles屬性、cellStyles屬性、以及styles屬性都是CSS樣式字串(注意必須以分號結尾),它們分別應用於表頭儲存格、內容儲存格,以及所有儲存格。另外,headerClasses屬性、cellClasses屬性、以及classes屬性則是以空格分隔的CSS類名,分別用於各自對應的儲存格。
<style>.firstName { font-style: italic;}.lastName { font-weight: bold;}</style><script>grid = new dojox.grid.DataGrid({ store: store, query: { id: "*" }, structure: [ { name: "First Name", field: "first", width: "84px", classes: "firstName" }, { name: "Last Name", field: "last", width: "84px", cellClasses: "lastName" }, { name: "Bats", field: "bats", width: "70px", cellStyles: "text-align: right;" }, { name: "Throws", field: "throws", width: "70px" }, { name: "G", field: "totalG", width: "60px" }, { name: "AB", field: "totalAB", width: "60px" }, { name: "Games as Batter", field: "totalGAB", width: "120px", styles: "text-align: center;" }, { name: "R", field: "totalR", width: "60px" }, { name: "RBI", field: "totalRBI", width: "60px" }, { name: "BB", field: "totalBB", width: "60px" }, { name: "K", field: "totalK", width: "60px" }, { name: "H", field: "totalH", width: "60px" }, { name: "2B", field: "total2B", width: "60px" }, { name: "3B", field: "total3B", width: "60px" }, { name: "HR", field: "totalHR", width: "60px" } ]}, "grid");</script>
【樣本】
子行
現在我們已經定義好了所有需要顯示的資料欄位,但看起來並不是很舒服。子行可以使某些資料更易閱讀、更易理解。要定義子行,需要給DataGrid傳一個儲存格定義的數組的數組。子行允許我們在
儲存格定義中使用兩個新的屬性:rowSpan定義了一個儲存格佔用多少子行,而colSpan則定義了一個儲存格佔用多少列。
注意:colSpan不能在第一個子行的儲存格中定義,這是因為DataGrid使用了table-layout: fixed;樣式來加速行的渲染。
grid = new dojox.grid.DataGrid({ store: store, query: { id: "*" }, structure: [ [ { name: "First Name", field: "first", width: "84px", rowSpan: 2 }, { name: "Last Name", field: "last", width: "84px", rowSpan: 2 }, { name: "Bats", field: "bats", width: "70px", rowSpan: 2 }, { name: "Throws", field: "throws", width: "70px", rowSpan: 2 }, { name: "G", field: "totalG", width: "60px" }, { name: "AB", field: "totalAB", width: "60px" }, { name: "R", field: "totalR", width: "60px" }, { name: "RBI", field: "totalRBI", width: "60px" }, { name: "BB", field: "totalBB", width: "60px" }, { name: "K", field: "totalK", width: "60px" } ],[ { name: "Games as Batter", field: "totalGAB", colSpan: 2 }, { name: "H", field: "totalH" }, { name: "2B", field: "total2B" }, { name: "3B", field: "total3B" }, { name: "HR", field: "totalHR" } ] ]}, "grid");
【樣本】
視圖
我們已經讓資料變得易讀一些了,但是,一旦你將grid滾動到最右端,你就無法看到每條記錄對應的球員是誰了。通過編寫一個視圖定義,我們能夠鎖定一組列,避免它們被左右滾動,從而始終保持可見。一個視圖定義是一個具有如下特定屬性的對象:
- cells:一個儲存格定義的數組、或這個數組的數組
- noscroll:一個布爾值,當為true時該視圖不顯示捲軸(橫向縱向都不顯示——譯者注)
- width:設定視圖寬度的CSS寬度字串。這個寬度只有在儲存格寬度採用的是相對值(例如百分比)的時候才有效
grid = new dojox.grid.DataGrid({ store: store, query: { id: "*" }, structure: [ { noscroll: true, cells: [ { name: "First Name", field: "first", width: "84px" }, { name: "Last Name", field: "last", width: "84px" } ] },{ cells: [ [ { name: "Bats", field: "bats", width: "70px", rowSpan: 2 }, { name: "Throws", field: "throws", width: "70px", rowSpan: 2 }, { name: "G", field: "totalG", width: "60px" }, { name: "AB", field: "totalAB", width: "60px" }, { name: "R", field: "totalR", width: "60px" }, { name: "RBI", field: "totalRBI", width: "60px" }, { name: "BB", field: "totalBB", width: "60px" }, { name: "K", field: "totalK", width: "60px" } ],[ { name: "Games as Batter", field: "totalGAB", colSpan: 2 }, { name: "H", field: "totalH" }, { name: "2B", field: "total2B" }, { name: "3B", field: "total3B" }, { name: "HR", field: "totalHR" } ] ] } ]}, "grid");
【樣本】
視圖定義還提供了一個很有用的屬性,能夠減少冗餘代碼:defaultCell。這個屬性允許你定義預設的儲存格屬性,如果儲存格定義中沒有同名屬性,那麼DataGrid將自動採用這些屬性:
grid = new dojox.grid.DataGrid({ store: store, query: { id: "*" }, structure: [ { noscroll: true, defaultCell: { width: "84px" }, cells: [ { name: "First Name", field: "first" }, { name: "Last Name", field: "last" } ] },{ defaultCell: { width: "60px" }, cells: [ [ { name: "Bats", field: "bats", width: "70px", rowSpan: 2 }, { name: "Throws", field: "throws", width: "70px", rowSpan: 2 }, { name: "G", field: "totalG" }, { name: "AB", field: "totalAB" }, { name: "R", field: "totalR" }, { name: "RBI", field: "totalRBI" }, { name: "BB", field: "totalBB" }, { name: "K", field: "totalK" } ],[ { name: "Games as Batter", field: "totalGAB", colSpan: 2 }, { name: "H", field: "totalH" }, { name: "2B", field: "total2B" }, { name: "3B", field: "total3B" }, { name: "HR", field: "totalHR" } ] ] } ]}, "grid");
【樣本】
可見,通過在defaultCell中設定width屬性,我們只需要為不同於這個預設值的列設定width屬性即可。
注意:如果儲存格定義裡和預設設定裡都沒有指定,那麼列的預設寬度是6em。
分頁與虛擬滾動
由於曆史原因,當一大堆資料需要顯示時,開發人員會採用一種稱為“分頁”的技術:任一時刻只有一小部分(大約25-50條記錄)資料才會被顯示。使用者可以使用按鈕或其他控制項在“頁面”之間切換。
但有了滾輪(也有人會說滑鼠)之後,分頁控制項就顯得有點笨重了。
DataGrid採用了一種略微不同的技術,稱為虛擬滾動:分頁瀏覽時,使用者只需要滾動滾輪即可。這種技術被稱為“虛擬滾動”是因為雖然看起來有很長的一串記錄,但任一時刻卻只有很小一部分資料被渲染出來。然而,DataGrid仍然使用了分頁技術,當使用者滾動時,資料被一頁一頁地從伺服器(或者dojo的store資料來源)請求過來。而且,預設情況下最近渲染的三頁資料被原封不動地保留著,以防使用者復原到原來的地方。每頁資料的行數可以由DataGrid的rowsPerPage屬性控制,而需要暫時保留渲染結果的行數則由keepRows屬性控制。
注意:要計算DataGrid將保留幾頁資料,只需要算keepRows除以rowsPerPage就行了。
結論
dojox.grid.DataGrid是一個強大的組件,它既可以渲染龐大的資料集,也能夠顯示由子行構成的複雜結構。而且它還讓使用者無需點擊任何控制項,單憑滾動滾輪即可瀏覽長列表。在下一篇教程中,我們將研究dojox.grid.DataGrid是如何與dojo的資料來源data store整合的。
參考
DataGrid官方文檔