解决前端js,处理上万条数据的渲染,加载卡顿的问题

应用背景

去年五月刚进公司,同事让我尝试处理网页数据渲染卡顿的问题。问题是这样:页面样式类似tab面板切换,按照分类一次性把上万条数据渲染上去,你鼠标往下滚动,表格数据一卡一卡的,几乎动不了。(==!本来做成分页就不会有这种问题,只是同事跟我说这项目的前端是外包出去的,如果要改样式,要写研发申请单,可能自己直接在js上处理数据比较快)
样式参考下图
图1-1
因为后端数据库也用了索引,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 =
                '                <tr onclick="alarmTrChangClass(this)" >\n' +
                '                    <td><i></i></td>\n' +
                '                    <td title="'+ k.reportMes +'">' + k.reportMes + '</td>\n' +
                '                    <td title="'+k.deviceName+'"><a onclick="onMsg(\''+k.id_record+'\')">' + repalceDeviceName(k.deviceName)+ '</a></td>\n' +
                '                    <td>' + repalceReportType(k.reportType)+ '</td>\n' +
                '                    <td>' + k.creatOn + '</td>\n' +
                '                    <td>\n' +
                '                        <button id="btn'+k.id_record+'" attr1="'+k.solve+'" attr2="'+k.id_record+'" onclick="changeAlarmStatus(this)">' + alarmDict[k.solve] + '</button>\n' +
                '                    </td>\n' +
                '                </tr>\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('<tr style="display:none;">');
    	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)<groups.length){
    				$('#countC').val(countT);
    				//分批渲染
    				loadGroup(ar7_tab,groups[countT]);
        		}
    		}
    	});
        
    }

以上,前端数据的渲染优化代码虽然比较原生态,复用性也不强,不过好处是根据大多使用场景,鼠标不可能一次性直接滑到底部(万级数据了,没有人这么无聊吧),也就是有很多数据都是不需要渲染的,无形中也减小了页面加载的执行压力。至少页面卡顿的问题算是解决了: )
当然,能做分页的话就不会碰到这种问题了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值