antv表格大量資料卡頓問題(區域性渲染資料)
阿新 • • 發佈:2020-09-16
表格最大資料量也就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>