EasyUI-datagrid大数据量加载缓慢的解决方案

博主在某系统的开发中遇到的问题可谓连串。例如由于各种原因,系统要求对windows自带的ie浏览器有着极高的兼容性要求,而最低兼容的ie版本低到了xp时代的ie8,这反而给了高速发展的技术出了一个难题。

在开发完成了一个个页面之后,我们开始对它们进行大量测试。由于业务要求,这些页面并不需要分页,也就是说所有数据需要一次性从数据库取出来,并加载到datagrid中。在开发初期由于只使用了少量自建的数据所以并没有发现什么异常。但当加载压力测试开始时,我们都傻眼了:800条数据在ie上加载完毕竟然需要40s以上!

这是一个绝对不能容忍的漫长!在查询了相关资料后我们发现了datagrid滚动加载插件:datagrid-scrollview.js。插件的使用很简单:

1、在html头中引入js文件

2、在datagrid中设置两个属性view:scrollview,pageSize:15

其中view属性指定了datagrid加载类型,scrollview就是滚动加载。pageSize一般在分页中当作每页行数,在这里官方把它作为每次滚动加载的行数。例如这里pageSize15,那么第一次加载时会加载30行,然后当滚动条向下滚动超过30条时每次加载15条。完成这些后我们又进行了简单测试,加载速度一下减少到2s左右,这个速度已经完全满足正常使用,因为毕竟还有行编辑功能的存在。

但随后我们却发现了一个更另令人失望的的问题:datagridcheckbox勾选和滚动加载完全不兼容,勾选完成之后,只要出现滚动加载出新数据,之前的勾选状态全部被清空,用getChecked无法取到勾选数据。这可是官方的插件啊!难道没经过严谨的测试么?在寻找了一系列解决和替代方案后都没有结果,无奈最后我们做出了一个之前没敢尝试过的决定:修改官方插件源码。

1、首先我们找到了官方插件不记录选中行的原因

可以看出在每次滚动加载的时候官方插件并没有获取到checkboxvalue,上图是在选中第一行之后的,可见checkbox的value是underfined。因为每次滚动的数据直接从第一次加载的原始数据中取,第一次加载完成的原始数据中当然不会有勾选状态。在找到的这个原因之后我们决定增加一个勾选状态的数组,并通过这个数组手动记录每行的勾选情况,并在每次滚动加载之后重新加载勾选状态。

2、增加全局变量用于记录勾选状态

var ckrow = new Array();

var tableRows = new Array();

var tableRowIndex = 0;

其中

ckrow用于记录每一行的选中状态以及全选框的勾选状态。

tableRows用于记录单次加载的那15行数据的实际行号。

tableRowIndex用于记录每次加载的那15行行号,从0到14。

3、在每次滚动加载时记录当前行号。

4、每次滚动后重新加载前tableRowIndextableRows都会被清空,用以记录新的数据的勾选情况。

5、记录所有行的勾选状态

下图就是需要在datagrid里面增加的了,每一次的勾选,取消勾选,全选以及取消全选都要改变ckrow中的记录,这样ckrow才能准确记录实际勾选情况。

6、把ckrow中记录的勾选状态还原到显示出来的行中

每次滚动之后,会执行上图代码,把ckrow中记录的勾选状态还原到datagrid中,同时从ckrow中取出ckrow['all']的值,这个时记录的全选框勾选状态的,再把这个值赋给$("input[type='checkbox']")[0] ,$("input[type='checkbox']")[0] 其实就是全选框,但是要注意的是如果在这个页面中,在全选框之前还有1个checkbox,则需要把[0]改为[1],如果全选框之前有俩个checkbox则改为[2],以此类推。

7、判断是否被全选

判断是否全选是在onCheck时触发,如5图,因为官方插件并不能在所有行被勾选的情况下自动选中全选框,所以这个动作也只能由我们自己完成了。判断是否被全选的过程其实就简单了。就是对currRows进行循环(currRows是从数据库中查询出来的所有行数据,也就是datagrid要展示的所有数据)用i依次核对每一行是否被勾选,只要有任何一行没被勾选则全选框不勾选,如果直到最后一行都是被勾选的,则把全选框勾选上。

8、再次loadData前清空所有勾选

因为上一次查询结果的操作记录是我们自己加上的,如果不处理,在datagrid重新loadData之后会自动勾选上上次勾选的那些行号对应的行,所以在下一次loadData之前需要清空上一次ckrow和勾选信息,以确保两次loadData之间没有任何干扰。

9、通过以上步骤datagrid在滚动加载时的展示方面问题已经全部被解决了,现在也就剩下最后一个问题了:如何取数据?

官方的勾选都是有问题的,现在的勾选框状态又是我们自己强硬加上的,所以肯定也不能通过官方自带的getChecked或者getSelections来获取选中行的数据了。所以这里我们又专门写了一个获取选中行数据的方法,如下图:

这个其实不难理解,主要就是把当前所有数据,和勾选记录进行对比,返回所有被勾选的行。另外一点在之前要先看是否被全选,如果是则直接返回当前所有数据,这样就大大节约了对比耗时增加了页面反应速度。

结尾:

至此一个官方自带bug的插件已经被完全修复,经过测试各项性能和质量都满足实际需求。

这次对官方源码的修改体现了以下思想:

1、状态和数据分离,这样在加载时不用管勾选状态,滚动加载还是利用官方自带的scrollview,这样的好处就是极大加快了大数据量下的加载速度。同时在用户手动点击勾选时记录每一行的勾选状态,直到用户需要取数据时才将两者进行匹配。

2、对于全局变量初始化以消除可能出现的干扰,全局变量的使用大大方便了很多功能的开发,但是同时也容易导致很多问题。所以在两次相同场景的使用中间需要对这些全局变量进行适当的初始化操作。

3、修改官方文件后需要进行大量测试,大多数情况下并不会遇到官方提供的技术出现这种重大问题的情况。毕竟官方在发布版本之前肯定做了大量测试,所以在实在需要修改这些文件后,我们需要做各种场景下的测试,这次的问题从发现到前期的修改方案选择,再到后期各种小问题的缺陷修改直至完全解决前后经历了两周时间。由此可见,修改源文件并不是一项轻松的工作。

最后感谢开发小组所有成员,在问题解决上提供了很多帮助,提出了很多问题和建议,也使得问题顺利解决。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171214G0MJAU00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励