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+
2246const 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