解决方案Dojo 网格的性能问题主要与输入/输出操作、大量数据访问和浏览器数据呈现有关。可以通过使用合并网格特性的机制来提升 Dojo 网格小部件的性能。
回顾缓存机制的使用。当数据从数据库加载到本机时,在内存中保存数据一段时间。这是减小服务器端请求数据的响应时间的好办法。这样直到用户更新或修改网格中的数据时才发送请求。缓存机制一般是通过 Dojo 网格本身实现的,但用户对网格进行某种操作时,问题就会发生。以下场景揭示了这些问题:
对网格排序多数情况下,可对网格正确排序,因为网格本身在数据存储层实现了排序函数。但数据存储会影响缓存。例如,如果网格列的类型是汉字,排序结果可能会不正确,而且网格的性能会由于某些不确定因素而严重下降。 解决方案是您自己在数据存储层重定义排序函数。下方的 和 演示了怎么做:根据 onHeaderCellMouseDown 函数重写排序逻辑,呈现数据,并更新网格的头部标题视图。
清单 13. 重定义排序逻辑1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| grid.onHeaderCellMouseDown = function(event){
var items = DataStore.data.items;
//Sort the "Name" column which might contain characters like Chinese and so on
if (event.cellIndex == 1) {
sortAscending = ! sortAscending ;
//Change the string to localestring before comparison with localeCompare method
if (sortAscending) {
items.sort(function(m, n){
return m["name"].toString().
localeCompare(n["name"].toString());
});
}else {
items.sort(function(m, n){
return n["name"].toString().
localeCompare(m["name"].toString());
});
}
}else
//Sort the "Date" column
if (event.cellIndex == 2) {
sortAscending = !sortAscending;
//Compare the date with milliseconds computed from 1970/07/01
if (sortAscending) {
items.sort(function(m, n){
return Date.parse(m["date"].toString())
- Date.parse(n["date"].toString());
});
}else {
items.sort(function(m, n){
return Date.parse(n["date"].toString())
- Date.parse(m["date"].toString());
});
}
}
}
|
清单 14. 呈现数据,更新网格头部视图1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| //"sorColIdx" is the index of the column to be sorted
updateGridAfterSort : function(sortColIdx){
//Render the data of the grid
var store = new dojo.data.ItemFileWriteStore(DataStore.data);
grid.setStore(store, null, null);
grid.update();
//Update the header view of the gird
var headerNodeObjs = document.getElementsByTagName("th");
for (var i = 0; i < 2; ++i) {
//"gridLayout" is a global array defining the layout of the grid
var headerNodeObjName = gridLayout[0].cells[0].name;
var headerNodeHtml = ['<div class="dojoxGridSortNode'];
if (i == sortColIdx){
headerNodeHtml = headerNodeHtml.concat([' ', (sortAscending ==
true) ? 'dojoxGridSortUp' : 'dojoxGridSortDown', '"><div
class="dojoxGridArrowButtonChar">', (sortAscending == true) ?
'▲' : '▼', '</div ><div class="dojoxGridArrowButtonNode"
></div >']);
headerNodeHtml = headerNodeHtml.concat([headerNodeObjName,
'</div>']);
headerNodeObjs.innerHTML = headerNodeHtml.join(" ");
break;
}
}
}
|
在网格中查找当网格有大量数据时,查找函数将会导致性能低下,尤其是当网格支持实时查找和模糊匹配特性时。解决方案是在它们被转换成数据存储中使用的 JSON 对象前,用额外的存储空间缓存数据;这将避免大量的函数调用,如数据存储的 getItem。 显示了一个样例。 清单 15. 将从数据库取出的数据缓存到数组中,并查找1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| //Fetch data from database
getData : function() {
function callback(ResultSet) {
//ResultSet is an array of records fetched from database and make variable
//rawData refer to it to cache it in memory
GlobalVaribles.rawData = ResultSet;
//Convert the raw data ResultSet to JSON for data store use
GlobalVaribles.dataJSON = JSONUtil.convert2JSON(ResultSet);
}
DBUtil.fetchAll(callback);
}
//Search functionality
search: function(col, value){
if (value == null || value == "") {
return;
}
//Used here
var rawData = GlobalVaribles.rawData;
var newResults = [];
for (var i = 0; i < rawData.length; i++) {
var result = rawData;
//Fuzzy match
if(result[col].toLowerCase().indexOf(value.toLowerCase()) != -1){
newResults[newResults.length] = result;
}
}
//Render the new results
GridManager.renderNewResults(newResults);
}
|
延时加载机制Dojo 网格原本就支持延时加载机制,这可以改善性能并提供更好的用户体验。Dojo 网格中的延时加载意味着在数据存储中呈现某些数据,但不是所有网格在您拖动滚动条时再显示其余的数据。 默认情况下,网格不会启用延时加载机制;必须显式启动。 演示了用两种方法启动。rowsPerPage 和 keepRows 属性是关键组件。
清单 16. 启动演示加载机制1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| //The programmatic way
var grid = new dojox.grid.DataGrid({
store: store, //data store
structure: gridLayout,
rowsPerPage: 10, //Render 10 rows every time
keepRows: 50, //Keep 50 rows in rendering cache
}, "grid");
//The declarative way using HTML label
<table
dojoType="dojox.grid.DataGrid"
id="grid" store="store" structure="gridLayout"
query="{ id: '*' }"
rowsPerPage="10" keepRows="50">
<!-- other definitions -->
</table>
|
前置加载机制前置加载机制可提前加载其余的数据,即使用户只是临时使用。对于 Dojo 网格,数据存储中可能有很多的数据;用户可能会拖动滚动条查看其余数据。如果一个页面中有很多数据,看某一特定行就不方便。使用前置机制和分页技术可更方便查看(与 Google 的分页条类似),并获得更好的性能。 显示的是分页技术的基本实现。首先,构造一些 JSON 对象,供数据存储用于初始分页条,然后当用户单击分页条的最后一页时添加一些新的 JSON 对象。
清单 17. 开始时构建一些 JSON 对象并根据需要切换1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| //Fetch data from database and convert them to JSON objects
getData : function() {
function callback(ResultSet) {
GlobalVaribles.rawData = ResultSet;
//"convert2JSONs" method convert the raw data to several JSON objects
//stored in Global array "dataJSONs".
GlobalVaribles.dataJSONs = JSONUtil.convert2JSONs(ResultSet);
}
DBUtil.fetchAll(callback);
}
//Initial status
var dataStore = new dojo.data.ItemFileWriteStore({data:GlobalVaribles.dataJSONs[0]});
var grid = new dojox.grid.DataGrid({
store: dataStore ,
structure: gridLayout,
}, "grid");
grid.startup();
//Assuming that the user clicks the i-th item in the paging bar, we just update the data
//store for the grid simply and the performance is still very good.
dataStore = new dojo.data.ItemFileWriteStore({data:GlobalVaribles.dataJSONs[i-1]});
grid.setStore(dataStore, null, null);
grid.update();
|
|