前言
基于之前支持表单验证的el-table开发完成后,在数据量过大的时候,会出现渲染慢,表格卡顿等致命问题,而element-ui的el-table本身没有像antd一样提供虚拟列表的demo和相关支持,因此本文在上次的开发基础上,继而开展虚拟列表的开发。本次分为普通列表和树形列表两种,树形在普通列表上面多了一些情况考虑,例如展开收缩等。
虚拟列表
虚拟列表简单概述就是滚动分页,通过有限的视口来切片大量的数据,因为相比于js运算,渲染是一个很慢的过程,因此通过一定的js计算,保证更少的数据渲染,通常可以获得更好的用户体验。一般虚拟列表可以通过上下的动态padding值,来是滚动区域一直显示当前切片出的数据,以及通过transform的方法来动态移动可视区。transform这种方法理论上性能要好一些,因为浏览器渲染本身是分图层渲染的,而transform操作的视图,会被浏览器单独分层出来,渲染性能更优。
下图两种方式:
本次el-table 上的虚拟列表,采用了padding的方案,原因是transform 会使el-table的样式混乱,如果是自己开发的table或者其他魔改支持度较好的插件的话优先transform。
普通列表
首先看一下el-table 渲染300 条的速度。
本次的测试代码有300条,本身并不多,但是有8列都是插槽中渲染的表单组件,因此渲染速度要慢很多,时间花销6s+。(antd 的table渲染要快一些,后面说原因)
增加虚拟列表后渲染速度:
开发流程
step1
计算总高度
height = list.length * 65
// height 为列表实际总高度
// 65 为每一行的行高,根据实际修改
// list为实际数据长度
step2
计算上下padding值
paddingTop = scrollTop + "px";
paddingBottom = height - 10 * 65 - scrollTop + "px";
// scrollTop 为滚动的高度,即列表向下滚动的距离
// height 总高度
// 10为实际渲染的条数
step3
监听列表滚动,动态为列表设置padding等样式。
mounted() {
console.time("render300条时间:");
this.form.rows = new Array(300).fill(0).map((v, i) => ({
name: i,
children: []
}));
this.form.rows = [...this.form.rows];
this.setIndex(this.form.rows);
this.calcList();
this.$nextTick(() => {
this.debounceFn = _.d