antv表格大量数据卡顿问题(局部渲染数据)
表格最大数据量也就500左右,再多,dom太多,浏览器会卡顿。为了解决这个问题,同时保持表格原有功能,对数据做了优化。
特点:
1、保留原有antv的table的所有功能(antd-react 一样的道理,这里只贴vue代码,react抄一下函数即可)
2、数据切换流畅,无卡顿问题,头尾数据无空白问题
3、可视区域渲染数据,条数默认15条,可配置,注意和可视高度配合
4、写法很简单
思路: 默认每条数据高度一样,不换行。增加一个滚动条,滚动滚动条,根据百分比,计算要展示的数据
缺点:全选会触发2次数据的回调,这个暂时没处理;若表格换行,高度相差太大影响数据显示,需要配置合理的高度
贴一下代码,有需要的自己拷贝: ps:对分页的一些功能还没封装完,直接忽略,看核心部分即可
<template>
<div class="c-large-table">
<a-table
clas
:loading="loading"
:columns="columns"
:row-key="record => record.id"
:data-source="tableData"
:row-selection="selected ? { selectedRowKeys: selectedRowKeys, onChange: handleSelect, onSelectAll: handleSelectAll } : null"
@change="handleTableChange"
:pagination="pagination"
>
<template slot="name" slot-scope="name"> {{ name.first }} {{ name.last }} </template>
</a-table>
<!-- 虚拟滚动条 -->
<div class="sc" :style="{height: tableHeight+'px'}">
<div class="scbc" :style="{height: totalHeight+'px'}"></div>
</div>
</div>
</template>
<script>
const ROWS = 15, // 局部渲染的数据条数
HEIGHT = 29.6, // 每行的高度
TABLEHEIGHT = 446; // 表格可视高度
export default {
props: {
loading: {
type: Boolean,
default: false
},
dataSource: {
type: Array,
default: []
},
columns: {
type: Array,
default: []
},
pagination: {
type: Object,
default: {
current: 1,
pageSize: 20,
tota: 0,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: ["20", "50", "100", "200", "500", "1000", "2000"]
}
},
rows: { // 可视区域展示多少行
type: Number,
default: ROWS
},
rowHeight: { // 每行的高度
type: Number,
default: HEIGHT
},
tableHeight: { // 可是区域高度
type: Number,
default: TABLEHEIGHT
},
selected: { // 是否可选
type: Boolean,
default: false
},
selectChange: { // 可选的回调
type: Function,
},
},
data() {
return {
scrollEle: '',
tableData: [],
selectedRowKeys: [],
totalHeight: 446, // 数据总高度
idx: 0, // 当前开始下标
};
},
watch: {
dataSource () {
const { dataSource, rows, rowHeight } = this
this.tableData = dataSource.length > rows ? dataSource.slice(0, rows) : dataSource
this.totalHeight = dataSource.length * rowHeight
}
},
created() {
const { dataSource, rows, rowHeight } = this
this.tableData = dataSource.length > rows ? dataSource.slice(0, rows) : dataSource
this.totalHeight = dataSource.length * rowHeight
},
mounted() {
this.scrollEle = document.querySelector('.c-large-table .sc .scbc');
document.querySelector('.c-large-table .sc').addEventListener('scroll', this.handleScroll);
},
methods: {
onShowSizeChange(current, pageSize) {
this.$emit("onShowSizeChange", current, pageSize);
},
pageChange(current, pageSize) {
this.$emit("onChange", current, pageSize);
},
handleTableChange() {
},
handleSelect(d, dl) {
this.selectedRowKeys = d
if(this.selected) this.$emit("selectChange", d, dl);
},
// 注意全选,需要手动填充数据
handleSelectAll(d,dl) {
let keys = [], dates = []
if(d) {
keys = this.dataSource.map(item => item.id)
dates = [...this.dataSource]
}
this.handleSelect(keys, dates)
},
// 监听虚拟滚轮变化,计算展示的数据
handleScroll(e) {
const { scrollTop, scrollHeight } = e.target
let lenMax = this.dataSource.length, nIdx;
if(scrollTop === 0) {
this.tableData = this.dataSource.slice(0, this.rows)
this.idx = 0
} else if(scrollTop === (scrollHeight - this.tableHeight)) {
nIdx = lenMax - this.rows
this.tableData = this.dataSource.slice(nIdx, nIdx + this.rows)
this.idx = nIdx
} else {
nIdx = Math.ceil(scrollTop * lenMax / scrollHeight)
if(nIdx !== this.idx && nIdx <= (lenMax - this.rows)) {
this.tableData = this.dataSource.slice(nIdx, nIdx + this.rows)
this.idx = nIdx
}
}
},
},
};
</script>
<style lang="less" >
.c-large-table {
position: relative;
.ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 4px 10px;
}
.sc {
position: absolute;
top: 28px;
right: -6px;
width: 16px;
overflow-x: hidden;
overflow-y: scroll;
.scbc {
border-radius: 2px;
background-color: #F1F1F1;
}
}
}
</style>

浙公网安备 33010602011771号