解决前端js,处理上万条数据的渲染,加载卡顿的问题
前言
很早就想开始通过博客用来记录和分享自己工作上遇到和解决的一些问题,还有日常学习的总结和收获。只是一直拖着,现在开始尝试,每日至少分享一次自己学有所得的内容。
应用背景
去年五月刚进公司,同事让我尝试处理网页数据渲染卡顿的问题。问题是这样:页面样式类似tab面板切换,按照分类一次性把上万条数据渲染上去,你鼠标往下滚动,表格数据一卡一卡的,几乎动不了。(==!本来做成分页就不会有这种问题,只是同事跟我说这项目的前端是外包出去的,如果要改样式,要写研发申请单,可能自己直接在js上处理数据比较快)
样式参考下图

因为后端数据库也用了索引,springboot的系统线程池也设定好参数,我在浏览器用new Date测试ajax的前后时间,回调一条记录和回调上万条记录的时间误差不超过1s;那这种页面加载的卡顿问题主要应该是在渲染的过程中了,谷歌搜了一下,好像是“浏览器内核自身支撑体系运行消耗太大,做js逻辑处理,还要做大量渲染”;所以优化方向就是主要渲染这一方面了(这些原理知识,以后了解更深了,会及时回来进一步解释或更正,如有不对,还请指正)。
看了一些文章,后来在知乎上找到【陈大侠】一篇比较明朗的,链接:转知乎
文章思路:获取后端回调的上万条数据后,存在js里,做分组处理。然后在for遍历方法体中使用setTimeout让程序每隔1ms渲染一次,强制“休息”1ms。
这样的效果页面数据的渲染虽然顺畅了,但也仅是前面的数据,鼠标越往下滚动,表格数据还是会卡顿。
这里我在文章里原来的基础上做了改动,让表格的数据,根据鼠标滚动(滚动高度/表格高度的整数比)来分批次加载。
代码如下:
//数据分组function group(data) {var result = [];var groupItem;for (var i = 0; i < data.length; i++) {if (i % 100 == 0) {!groupItem && result.push(groupItem);groupItem = [];}groupItem.push(data[i]);}result.push(groupItem);return result;}
首先,上面代码将后端返回的数据进行分组,比如我这里设定每组100条记录。然后进行渲染,如下:
//遍历、渲染的通用函数function loadGroup(ar7_tab,group){group.forEach((k,v) => {let tr =' \n' +' \n' +' ' + k.reportMes + ' \n' +' ' + repalceDeviceName(k.deviceName)+ ' \n' +' ' + repalceReportType(k.reportType)+ ' \n' +' ' + k.creatOn + ' \n' +' \n' +' \n' +' \n' +' \n';let $tr = $(tr);if (!!alarmTitle&&alarmTitle.id_record&&k.id_record == alarmTitle.id_record) {$tr.addClass("ar7-point");}ar7_tab.append($tr);});}
function rerendAlarmTab(ar7_tab ,data ) {//数据渲染主函数ar7_tab.append('');var groups = group(data); //将后端接收到的数据按100条为单位,进行分组loadGroup(ar7_tab,groups[0]);//页面加载的首批渲染 //鼠标滚动$('#ar7-tab').scroll(function(){//鼠标滚动的高度 >表格固定高度时if($(this).scrollTop() >= $(this).height()){let countT=$(this).scrollTop()/$(this).height();countT=countT.toString().split(".")[0];//取整数倍数(高度比)//鼠标不往回滚(鼠标回滚数据不继续加载) && 小于数据组总长度(未加载完)if(parseInt(countT)>parseInt($('#countC').val()) && parseInt(countT)
以上,前端数据的渲染优化代码虽然比较原生态,复用性也不强,不过好处是根据大多使用场景,鼠标不可能一次性直接滑到底部(万级数据了,没有人这么无聊吧),也就是有很多数据都是不需要渲染的,无形中也减小了页面加载的执行压力。至少页面卡顿的问题算是解决了: )
当然,能做分页的话就不会碰到这种问题了。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
