el-table虚拟列表实现代码
时间: 2023-10-14 15:15:57 浏览: 77
以下是el-table虚拟列表的实现代码:
```javascript
<template>
<el-table
ref="table"
:data="tableData"
:row-key="row => row.id"
:height="tableHeight"
:row-height="rowHeight"
:header-row-height="headerRowHeight"
:v-loading="loading"
:default-sort="defaultSort"
@sort-change="handleSortChange"
@row-click="handleRowClick"
@row-contextmenu="handleRowContextMenu"
>
<el-table-column
v-for="column in columns"
:key="column.prop"
:label="column.label"
:prop="column.prop"
:min-width="column.minWidth"
:resizable="column.resizable"
:formatter="column.formatter"
:sortable="column.sortable"
:sort-method="column.sortMethod"
:align="column.align"
:header-align="column.headerAlign"
:show-overflow-tooltip="column.showOverflowTooltip"
:fixed="column.fixed"
/>
</el-table>
</template>
<script>
import { debounce } from 'lodash'
export default {
name: 'VirtualTable',
props: {
columns: {
type: Array,
required: true
},
data: {
type: Array,
required: true
},
total: {
type: Number,
required: true
},
loading: {
type: Boolean,
default: false
},
height: {
type: Number,
required: true
},
rowHeight: {
type: Number,
default: 40
},
headerRowHeight: {
type: Number,
default: 40
},
defaultSort: {
type: Object
},
fetch: {
type: Function,
required: true
}
},
data() {
return {
tableData: [],
scrollTop: 0,
startRow: 0,
endRow: 0,
visibleRowCount: 0,
requestParams: {},
sort: null
}
},
computed: {
tableHeight() {
return this.height - this.headerRowHeight
},
visibleRowStartIndex() {
return Math.floor(this.scrollTop / this.rowHeight)
},
visibleRowEndIndex() {
return Math.floor((this.scrollTop + this.tableHeight) / this.rowHeight)
},
isAllDataLoaded() {
return this.endRow === this.total - 1
}
},
watch: {
data() {
this.loadData()
}
},
mounted() {
this.loadData()
this.$refs.table.bodyWrapper.addEventListener('scroll', debounce(this.handleScroll, 50))
},
methods: {
async loadData() {
this.tableData = []
this.startRow = 0
this.endRow = 0
this.visibleRowCount = 0
if (this.data.length > 0) {
await this.loadRows()
this.$refs.table.doLayout()
}
},
async loadRows() {
this.requestParams = {
start: this.startRow,
end: this.endRow,
sort: this.sort
}
const result = await this.fetch(this.requestParams)
this.tableData = this.tableData.concat(result.data)
this.startRow = this.endRow + 1
this.endRow = this.startRow + result.data.length - 1
this.visibleRowCount = this.tableData.length
},
async handleScroll() {
const { scrollTop } = this.$refs.table.bodyWrapper
const scrollDistance = Math.abs(scrollTop - this.scrollTop)
if (scrollDistance > this.rowHeight) {
this.scrollTop = scrollTop
await this.updateVisibleRows()
}
},
async updateVisibleRows() {
let shouldLoadMore = false
if (this.visibleRowCount === 0) {
shouldLoadMore = true
} else if (this.visibleRowStartIndex > this.endRow || this.visibleRowEndIndex < this.startRow) {
shouldLoadMore = true
}
if (shouldLoadMore && !this.isAllDataLoaded) {
await this.loadRows()
}
},
async handleSortChange(sort) {
this.sort = sort
await this.loadData()
},
async handleRowClick(row, column, event) {
this.$emit('row-click', row, column, event)
},
async handleRowContextMenu(row, column, event) {
this.$emit('row-contextmenu', row, column, event)
}
}
}
</script>
```
该组件的实现主要是通过监听表格的滚动事件来动态加载数据,从而实现虚拟列表。同时,还有一些其他的功能,如排序、点击行、右键菜单等,都已经在代码中实现。需要注意的是,这里使用了 lodash 库中的 debounce 函数来控制滚动事件的触发频率。
阅读全文