element/Antd vue 表格性能问题,表格数据多导致页面卡顿问题解决思路与方法
工作中,使用了 Antd vue 中的 a-table 组件,当表格数据过多时导致页面卡顿,并且表格多选也会出现卡顿,测试提出了性能bug。。。
table 没有设计成分页那种加载数据的形式,而是用滚动加载的方式不停地加载数据,我也是醉了。。。
在百度了一圈后,发现解决该问题主要是用虚拟滚动的思路。引发页面卡顿的原因主要是由于数据量太大导致渲染的 dom 较多,然后页面就卡顿了。。。
下面使用 element 中的 el-table 实现一下虚拟滚动来解决这个问题,Antd vue 中的写法也类似,a-table 的结构相似。
1 先搞页面结构
<template>
<div>
<div class="gl-cell-card-box">
<el-table
ref="tableRef"
style="width:418px"
border
max-height="448"
:data="sliceTable"
:row-key="row => row.id"
@select="handleSelect"
@select-all="handleSelectAll"
>
<el-table-column type="selection" width="40"> </el-table-column>
<el-table-column prop="name" label="姓名" width="120"></el-table-column>
<el-table-column prop="age" label="年龄" width="120"></el-table-column>
<el-table-column prop="address" label="住址"></el-table-column>
</el-table>
</div>
</div>
</template>
2 定义一些变量
data() {
return {
tableData: [],
startIndex: 0,
selectedRows: [],
vEle: undefined,
isSelectedAll: false,
};
},
3 定义方法
computed: {
sliceTable() {
return this.tableData.slice(this.startIndex, this.startIndex + 9);
},
},
created() {
this.vEle = document.createElement("div");
this.loadData();
},
mounted() {
this.$refs.tableRef.$el
.querySelector(".el-table__body-wrapper")
.addEventListener("scroll", this.tableScroll, {
passive: true
});
},
methods: {
loadData() {
let start_i = this.tableData.length;
for (let i = start_i; i < start_i + 20; i++) {
this.tableData.push({
id: i,
name: "zhangsan" + i,
age: 12,
address: "china"
});
}
this.$nextTick(() => {
this.$refs.tableRef.$el.querySelector(".el-table__body").style.position = "absolute";
this.vEle.style.height = this.tableData.length * 48 + "px";
this.$refs.tableRef.$el.querySelector(".el-table__body-wrapper").appendChild(this.vEle);
this.selectedRows.forEach(row => {
this.$refs.tableRef.toggleRowSelection(row, true);
});
});
},
handleSelect(selection, row) {
this.selectedRows = selection;
},
handleSelectAll(selection) {
this.isSelectedAll = !this.isSelectedAll;
if (this.isSelectedAll) {
this.selectedRows = this.tableData;
} else {
this.selectedRows = [];
this.$refs.tableRef.clearSelection();
}
},
tableScroll() {
let bodyWrapperEle = this.$refs.tableRef.$el.querySelector(".el-table__body-wrapper");
let scrollTop = bodyWrapperEle.scrollTop;
this.startIndex = Math.floor(scrollTop / 48);
bodyWrapperEle.querySelector(".el-table__body").style.transform = `translateY(${this.startIndex * 48}px)`;
this.selectedRows.forEach(row => {
this.$refs.tableRef.toggleRowSelection(row, true);
});
if (bodyWrapperEle.scrollHeight <= scrollTop + bodyWrapperEle.clientHeight) {
if (this.tableData.length == 100) {
this.$message.warning("没有更多了");
return;
}
this.loadData();
}
}
}
参考文献
[1] vue针对滚动元素内部大量元素,但只有部分元素可见,对dom懒渲染,节省内存的优化 [2] antv表格大量数据卡顿问题(局部渲染数据)
|