原作者: Bryan Forbes 原文链接:http://dojotoolkit.org/documentation/tutorials/1.6/datagrid/ 译者:zhuxw (zhuxw1984@gmail.com) 鉴于DataGrid对于表格数据的有效呈现,它早已成为许多应用的核心组件之一。在
原作者: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则定义了一个单元格占用多少列。
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属性即可。
分页与虚拟滚动
由于历史原因,当一大堆数据需要显示时,开发者会采用一种称为“分页”的技术:任一时刻只有一小部分(大约25-50条记录)数据才会被显示。用户可以使用按钮或其他控件在“页面”之间切换。
但有了滚轮(也有人会说鼠标)之后,分页控件就显得有点笨重了。
DataGrid采用了一种略微不同的技术,称为虚拟滚动:分页浏览时,用户只需要滚动滚轮即可。这种技术被称为“虚拟滚动”是因为虽然看起来有很长的一串记录,但任一时刻却只有很小一部分数据被渲染出来。然而,DataGrid仍然使用了分页技术,当用户滚动时,数据被一页一页地从服务器(或者dojo的store数据源)请求过来。而且,默认情况下最近渲染的三页数据被原封不动地保留着,以防用户回滚到原来的地方。每页数据的行数可以由DataGrid的rowsPerPage属性控制,而需要暂时保留渲染结果的行数则由keepRows属性控制。
注意:要计算DataGrid将保留几页数据,只需要算keepRows除以rowsPerPage就行了。
结论
dojox.grid.DataGrid是一个强大的组件,它既可以渲染庞大的数据集,也能够显示由子行构成的复杂结构。而且它还让用户无需点击任何控件,单凭滚动滚轮即可浏览长列表。在下一篇教程中,我们将研究dojox.grid.DataGrid是如何与dojo的数据源data store整合的。