sunnylinner 2014-12-19
jQuery EasyUI的Datagrid组件功能算是很强大了,不过性能确实不怎么乐观,而对于性能问题,网络上几乎也找不到相关的优化资料,所谓的牛人们可能 都望而却步了。本博客以后会带着分析Datagrid组件的性能问题,并且给出优化方案,也希望大家能集思广益,给出一些好的想法。
以目前对Datagrid的了解程度去看待性能问题,主要有以下几点:
不考虑服务端返回数据的时间,在前台获取到大数据量后,往表格里插入tr的时候,IE执行的效率非常低,2000条数据要45秒左右,其他浏览器则很快。
通过单步调试发现,默认视图在最后将tr写到table里面用的是jQuery的html()函数,就是这个函数在IE下执行效率非常低。
jQuery是个很锋利的工具,可有时候我们也得返璞归真一下,为什么非要用jQuery的html()函数呢,我们就用javascript dom对象里面的innerHtml属性不就可以了么,而且换成innerHTML属性方式的话,效率提高几十倍。
所以,大数据量加载慢的问题,就这么简单就解决了,修改默认视图render方法最后那句:
改为:
注意:innerHTML虽然符合w3c标准,而且各个浏览器也都支持,但是表现出的行为却又差异,另类的浏览器依旧是IE,主要表现在以下几个方面:
幸运的是EasyUI的datagrid默认视图没有使用html5技术,调用innerHTML的节点也并非table节点(是div),而href,src等转化为绝对路径并没有什么影响。
VirtualScrollView视图官网已经写出来了,不过有两个Bug而已,我对这个视图的源码也分析过,请大家参照:
http://www.easyui.info/archives/1404.html
勾选和点选(开启singleSelect)慢的原因其实是一样的,都是选择器执行效率低,这里我拿勾选的情况来分析。
具体的分析过程我就不描述了,知道用chrome,fireBug,IE开发者工具调试的同学,应该都有定位问题的思路:先定位执行效率低的函数,再在函数内定位执行效率低的语句。
checkbox导致操作不流畅的原因,我最后定位到opts.finder.getTr这个方法上,我们来看它的代码片段:
这段代码是获取已经被勾选的rows,大家可以看到,这是纯粹的jQuery选择器查询,效率就慢在has这个伪选择器上,它是针对所有后代元素的,查找的效率是比较慢的,又是在这么多数据量的情况下,其效果就可想而知了。
其实对于checkbox列的DOM结构是固定的,我们完全可以用速度快的选择器来代替":has",我们先直接用路径选择器找到"input:checked",然后使用三次parent()函数返回tr,写法虽然复杂了,但是效率应该提高一点,所以我们改成这样:
我用自己的服务大概测试了修改前后的效率(jQuery版本1.8.0,EasyUI版本1.3.3,singleSelect为false,2000条数据勾选一条记录的测试情况):
浏览器执行时间浏览器执行时间原版IE9600mschrome60ms选择器优化IE9560mschrome60ms从上面的结果可以看出,在这种测试条件下,我们提高的效率并不大,IE9下提高的效率尽管有所提高,但是还是很不理想,而chrome下性能基本一 样。测试过程中发现,如果使用jQuery2.0的话,IE9下的执行时间将达到45000ms,几乎让人奔溃,看来尽管IE9勉强支持 jQuery2.x,但是效率很挫。
既然慢在DOM结构巨大时,jQuery选择器的搜索效率不是很好(特别是在IE下)。如果我们每次操作都记录下勾选的tr,那么就完全可以绕开选择器。
具体该怎么做呢,我们给$.data(target,'datagrid')变量增加两个属性:"checkedTrsBody1" 和"checkedTrsBody2"分别存储frozen部分和normal部分被勾选tr的引用,然后在各个设计到勾选的操作中维护这两个属性。最 后,获取被勾选tr的时候就可以直接从这两个属性中取了,其耗时是可以忽略的。
那么究竟哪些操作会影响到被勾选的tr呢,我们罗列一下,也就以下几 种:"checkRow","uncheckRow","uncheckAll","checkAll","deleteRow","loadData","load","reload". 我们只要在这些接口中维护起"checkedTrsBody1"和"checkedTrsBody2"属性就可以了。
至于具体的代码怎么改,我就不贴了,最好就直接改动源码了,思路很清晰,请各位自己去实现,是在理不出头绪的,请参照我的实现:
http://www.easyui.info/version/jquery-easyui-1.3.3/plugins/jquery.datagrid.js
勾选性能测试【IE9;jQuery-1.8.0;EasyUI-1.3.3;singleSelect:false】:
200条 | 7 | 64 |
500条 | 20 | 160 |
1000条 | 27 | 308 |
2000条 | 53 | 623 |
4000条 | 107 | 1323 |
6000条 | 192 | 2072 |
8000条 | 265 | 2865 |
10000条 | 331 | 3611 |
可以看出来,无论是在IE9下,勾选效率都提高了很多倍(chrome下效率也有显著提高)。开启singleSelect的优化思路是一样的,所以不写重复文字了。
渲染性能测试【IE9;不考虑服务器响应时间】:
200条 | 49 | 326 |
500条 | 122 | 1821 |
1000条 | 253 | 7002 |
2000条 | 525 | 27320 |
4000条 | 1083 | 110115 |
6000条 | 1683 | 200000 |
8000条 | 2261 | 200000 |
10000条 | 2900 | 200000 |
原版的datagrig,我本地的测试环境数据在4000条以上时,IE9基本就卡死了(可能机器性能不太好),无统计价值了,即便是4000条数据,也要将近2分钟才渲染完,显然没人能够忍受。
从报表很明显可以看出优化过的表格,即便是10000条数据,3秒也就渲染完成了。
未优化版本:http://www.easyui.info/version/jquery-easyui-1.3.3/demo/datagrid/bigdata_checkbox.html
优化版本:http://www.easyui.info/version/jquery-easyui-1.3.3/demo/datagrid/bigdata_checkbox_optimized.html