首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

提高 Dojo Grid 的数据处理性能(3)Grid 性能问题的解决方法

提高 Dojo Grid 的数据处理性能(3)Grid 性能问题的解决方法

Grid 性能问题的解决方法     要解决上述性能问题,需要解决三个方面的问题。
Step 1. 适时断开 Grid 和 Store 的连接
     因为往 Store 中添加数据的速度很快,而 Grid 的载入新加项和更新视图速度较慢,所以在操作之初,就把 Grid 的 Store 设置为空(null),     断开 Grid 和 Store 的连接 , deviceGrid._setStore(null);。这样即使 Store 因为 addItem 发生变化,也不会联动引起 Grid 的操作了。     当 Store 中添加完数据后再把 Grid 和 Store 链接上:deviceGrid._setStore(deviceStore); 最后把数据重新加载完成视图更新:deviceGrid.render()。     清单 7 中展示的就是这个过程,在添加数据之初 modelGrid 先断开 Store 的连接,再往 modelStore 中添加数据,结束后又把 modelStore 重新连接上 modelGrid.
清单 7. Grid 添加项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function _addGridData(dataarray)
{
modelGrid._setStore(null); // 断开连接
/* 往 Grid 中添加数据 */
for(var i=0;i<datalength;i++){
var modelname = dataarray.split(',')[0];
var devicename = dataarray.split(',')[1];   
modelStore.newItem({id:"modelItem"+i,StatusImage:'<img src="images/Normal_obj16.gif">',
Sel:true,Loop:1,Status:'<img src="images/statusStopped_obj16.gif">Not Started',
Model: modelname, Device: devicename});   
}
modelGrid._setStore(modelStore);// 恢复连接
modelGrid.render();// 重新加在视图
}




Step2. 适应“lazy loading”数据加载机制
     Dojo Grid 在获取 Item 时有一种机制叫做“lazy loading”。在 Grid 初始化时并不把 Store 里的所有数据都加载进来,     而是采用“on-demand”的方式进行数据加载。触发数据加载的事件是 Grid 滚动条的的拖拉动作。当滚动条被拖拉到某一个特定位置时,     Grid 会计算出当前滚动条的位置,并把和当前位置相关的数据加载进来。数据加载是按照“页”为单位装载的。有两个比较重要的属性:      
         keepRows: 75        // Number of rows to keep in the rendering cache          
         rowsPerPage: 25    //Number of rows to render at a time, and the rows number in each page              
在步骤 1 的最后,Grid 使用 render( ) 函数来取回表格、表头和视图,并把滚动条停留在 Grid 最顶端。因此,在 Grid 完成一次 render 后加载进来的数据只有 25 条。其余的数据要在用户拖动滚动条后触发再按需加载进来。

这样的数据加载方式,固然是减小了内存开销,提高了页面加载速度。但如果此时使用 Grid 的 getItemidx) 函数,程序会因为 getItem 函数中的 var data = this._by_idx[idx]; 语句而报错。因为输入函数 idx 可能大于当前 Grid 加载进来的数据量,此时通过 idx 去 Grid 中索引 Item 就会导致数组越界报错。也就是说在“lazy loading”的情况下,数据没有同时全部载入,这时如果企图通过 Grid.getItem(idx) 来操作 Store 中的所有数据的修改、删除是不安全的。

解决这一问题的方法是直接对 Store 中的数据进行获取、修改、删除。Store 中的 _arrayOfTopLevelItems 存储着的 Store 当前数据。因为这些数据和 Grid 的显示数据是一一对应,所以可以通过参数(Grid Item 的行数)把 Grid 的数据映射到 Store 中,直接对 Store 里的源数据进行操作。

清单 8 中展示的是如何通过直接存取 Store 中的数据来实现对 Grid 数据的操作。程序的第一段定义了 GetItemfromStore 函数,他有两个参数一个是 Store 的名称和需要索引的行数。有了这两个参数,就可以通过 Store._arrayOfTopLevelItems[idx] 获得对应的存储在 Store 中 Item 了。

修改 Item 比较简单,在函数 ModifyItem 中只要由 GetItemfromStore 得到 Item,然后对 Item 修改 setValue 就可以更改 Item 了。删除 Item 也同样是由 GetItemfromStore 得到 Item,然后取出 Item 中的某个属性判断该 Item 是否符合删除条件,如果符合就在 Store 中加以删除。结合 step1 中的操作 Store 前断开连接,操作完 Store 后恢复连接,就可以实现 Grid 的删除功能。
清单 8. 对 Store 中存储的 Item 直接操作
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
36
37
38
39
40
41
42
// 获得 Store 中的 Item
function GetItemfromStore(Store,idx)
{
var Item=eval(Store._arrayOfTopLevelItems[idx]);
return Item;
}

// 修改 Item
function  ModifyItem()
{  
for (var i=0;i<100;i++){
   var Item=GetItemfromStore(modelStore,i);
   modelStore.setValue(Item,'Loop',i);
   }
}
// 删除 Item
function DeleteItem()
{
var deletnum=0;
var pushidx=new Array;
modelGrid._setStore(null);// 断开连接
for(var i=0;i<modelGrid.rowCount;i++){
   var Item;
   Item=GetItemfromStore(modelStore,i);// 获得 Item
   if(Item !=null){
     var sel = modelStore.getValue(Item,'Sel');// 获得 Sel 属性   
     if(sel==true){
       deletnum=deletnum+1;
       pushidx.push(Item);// 把符合条件的 Itempush 到 Array 中去
     }
    }  
   }
   var Items = pushidx;
   /*Store 循环删除 Item*/
   if(Items.length){
        for(var i=0;i<Items.length;i++){
            modelStore.deleteItem(Items);
     }
   }
   modelGrid._setStore(modelStore);// 恢复连接
   modelGrid._refresh();//Grid 更新视图
}




Step3. 重构 Grid 的排序方法
    Grid 具有排序功能,点击表头可以实现对表格内容升序或者降序排列。每次排序的操作都是针对 Grid 加载进来的数据进行的。    排序后,当需要对数据操作时,还是先通过 Grid.getItem(idx) 获得 Item,然后依靠 Item 特有的 identifier 索引到 Store 中的真实数据,    再对数据进行修改。

    然而因为“lazy loading”的存在,Grid 并没有把所有数据同时加载进来,这就导致了 Grid 排序后会出现数据获得错误和数据索引错误。    所以为了保证数据索引正确,就需要从数据源上对数据进行排序,这样才能保证 Grid 和 Store 中的数据顺序保持一致。

    具体做法是先禁用 Grid 的默认 sort 方法:canSort="false"。然后重新定义 Grid.onHeaderCellMouseDown 的响应函数,    重构 sort 函数,以及更新 Grid 标题视图。这样就可以保证 Grid 的排序功能正常运行。
返回列表