vue3下element-plus解决el-table大数据加载优化

vue 3.0.5

element-plus 1.0.2-beta.40

vue自定义指令版本差异

使用自定义指令 局部,也可这是全局 loadmore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<template>
<div id="app">
<el-table
height="300"
:data="filteredData"
v-loadmore="handelLoadmore"
:data-size="table?.tableData.length"
style="width: 100%; border: 2px solid blue" fit border row-key="id"
stripe :highlight-current-row="true"
empty-text="暂无数据">
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
</el-table>
</div>
</template>

<script lang="ts">
import {
computed,
defineComponent,
reactive,
ref
} from 'vue'
const selfDirectives = {
loadmore: {
created(el, binding, vnode, prevVnode) {}, // 新增
beforeMount(el, binding, vnode) {
console.log('loadmore beforeMount')
},
mounted() {},
beforeUnmount() {}, // 新增
unmounted() {},
// componentUpdated → updated
updated(el, binding, vnode, oldVnode) {
// 设置默认溢出显示数量
var spillDataNum = 30
// 设置隐藏函数
var timeout = false
let setRowDisableNone = function (topNum, showRowNum, binding) {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
binding.value.call(
null,
topNum,
topNum + showRowNum + spillDataNum
)
})
}
setTimeout(() => {
// 其他UI框架关注 修改 获取 attr data属性
const dataSize = vnode.props["data-size"]
const oldDataSize = oldVnode.props["data-size"]
if (dataSize === oldDataSize) return;
const selectWrap = el.querySelector(".el-table__body-wrapper");
const selectTbody = selectWrap.querySelector("table tbody");
const selectRow = selectWrap.querySelector("table tr");
if (!selectRow) {
return;
}
const rowHeight = selectRow.clientHeight
let showRowNum = Math.round(selectWrap.clientHeight / rowHeight);
const createElementTR = document.createElement("tr");
let createElementTRHeight =
(dataSize - showRowNum - spillDataNum) * rowHeight;
createElementTR.setAttribute(
"style",
`height: ${createElementTRHeight}px;`
);
selectTbody.append(createElementTR);

// 监听滚动后事件
selectWrap.addEventListener("scroll", function () {
let topPx = this.scrollTop - spillDataNum * rowHeight;
let topNum = Math.round(topPx / rowHeight);
let minTopNum = dataSize - spillDataNum - showRowNum;
if (topNum > minTopNum) {
topNum = minTopNum;
}
if (topNum < 0) {
topNum = 0;
topPx = 0;
}
selectTbody.setAttribute(
"style",
`transform: translateY(${topPx}px)`
);
createElementTR.setAttribute(
"style",
`height: ${
createElementTRHeight - topPx > 0
? createElementTRHeight - topPx
: 0
}px;`
)
setRowDisableNone(topNum, showRowNum, binding);
})

})
}
}
}
export default defineComponent({
directives: selfDirectives,
setup() {
const table = reactive({
tableData: [],
currentStartIndex: 0,
currentEndIndex: 30,
})

const getList = () => {
let cont = 0;
let tableData = [];
while (cont < 100000) {
cont = cont + 1;
let object = {
name: "阿发" + cont,
age: cont,
sex: '男'
};
tableData.push(object);
}
setTimeout(() => {
table.tableData = tableData
}, 0)
}
getList()

const handelLoadmore = (currentStartIndex, currentEndIndex) => {
table.currentStartIndex = currentStartIndex;
table.currentEndIndex = currentEndIndex;
}

const filteredData = computed(() => {
let list = table.tableData.filter((item, index) => {
if (index < table.currentStartIndex) {
return false
} else if (index > table.currentEndIndex) {
return false
} else {
return true;
}
})
return list
})
return {
table,
filteredData,
handelLoadmore,
}
}
})
</script>