Skip to content

Commit 8dff457

Browse files
committed
优化虚拟列表
1 parent 850a429 commit 8dff457

File tree

1 file changed

+47
-10
lines changed

1 file changed

+47
-10
lines changed

src/renderer/components/base/VirtualizedList.vue

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<template>
2-
<component :is="containerEl" ref="dom_scrollContainer" :class="containerClass" tabindex="0" style="outline: none; height: 100%; overflow-y: auto; position: relative; display: block; contain: strict;">
2+
<component
3+
:is="containerEl"
4+
ref="dom_scrollContainer"
5+
:class="containerClass"
6+
tabindex="0"
7+
style="outline: none; height: 100%; overflow-y: auto; position: relative; display: block; contain: strict; box-sizing: border-box; will-change: transform;"
8+
>
39
<component :is="contentEl" :class="contentClass" :style="contentStyle">
410
<div v-for="item in views" :key="item.key" :style="item.style">
511
<slot name="default" v-bind="{ item: item.item, index: item.index }" />
@@ -19,6 +25,24 @@ import {
1925
onBeforeUnmount,
2026
} from 'vue'
2127
28+
/**
29+
* 生成防抖函数
30+
* @param {*} fn
31+
* @param {*} delay
32+
*/
33+
export const debounce = (fn, delay = 100) => {
34+
let timer = null
35+
let _args = null
36+
return function(...args) {
37+
_args = args
38+
if (timer) clearTimeout(timer)
39+
timer = setTimeout(() => {
40+
timer = null
41+
fn.apply(this, _args)
42+
}, delay)
43+
}
44+
}
45+
2246
const easeInOutQuad = (t, b, c, d) => {
2347
t /= d / 2
2448
if (t < 1) return (c / 2) * t * t + b
@@ -105,12 +129,14 @@ export default {
105129
setup(props, { emit }) {
106130
const views = ref([])
107131
const dom_scrollContainer = ref(null)
132+
let isListScrolling = false
133+
const isListScrollingRef = ref(false)
108134
let startIndex = -1
109135
let endIndex = -1
110136
let scrollTop = -1
111137
let cachedList = []
112138
let cancelScroll = null
113-
let isScrolling = false
139+
let isAutoScrolling = false
114140
let scrollToValue = 0
115141
116142
const createList = (startIndex, endIndex) => {
@@ -171,7 +197,14 @@ export default {
171197
scrollTop = currentScrollTop
172198
}
173199
200+
const setStopScrollStatus = debounce(() => {
201+
isListScrolling = false
202+
isListScrollingRef.value = false
203+
}, 200)
174204
const onScroll = event => {
205+
if (!isListScrolling) isListScrolling = isListScrollingRef.value = true
206+
setStopScrollStatus()
207+
175208
const currentScrollTop = dom_scrollContainer.value.scrollTop
176209
if (Math.abs(currentScrollTop - scrollTop) > props.itemHeight * 0.6) {
177210
updateView(currentScrollTop)
@@ -189,15 +222,15 @@ export default {
189222
}
190223
}).then(() => {
191224
if (animate) {
192-
isScrolling = true
225+
isAutoScrolling = true
193226
scrollToValue = scrollTop
194227
cancelScroll = handleScroll(dom_scrollContainer.value, scrollTop, 300, () => {
195228
cancelScroll = null
196-
isScrolling = false
229+
isAutoScrolling = false
197230
onScrollEnd(true)
198231
}, () => {
199232
cancelScroll = null
200-
isScrolling = false
233+
isAutoScrolling = false
201234
onScrollEnd('canceled')
202235
})
203236
} else {
@@ -217,17 +250,21 @@ export default {
217250
}
218251
219252
const getScrollTop = () => {
220-
return isScrolling ? scrollToValue : dom_scrollContainer.value.scrollTop
253+
return isAutoScrolling ? scrollToValue : dom_scrollContainer.value.scrollTop
221254
}
222255
223256
const handleResize = () => {
224257
window.setTimeout(updateView)
225258
}
226259
227-
const contentStyle = computed(() => ({
228-
display: 'block',
229-
height: props.list.length * props.itemHeight + 'px',
230-
}))
260+
const contentStyle = computed(() => {
261+
const style = {
262+
display: 'block',
263+
height: props.list.length * props.itemHeight + 'px',
264+
}
265+
if (isListScrollingRef.value) style['pointer-events'] = 'none'
266+
return style
267+
})
231268
232269
const handleReset = list => {
233270
cachedList = Array(list.length)

0 commit comments

Comments
 (0)