From 5ac40bfa156cc58a618d72bbb087f4b40ba47f29 Mon Sep 17 00:00:00 2001 From: loyoi <1019748371@qq.com> Date: Fri, 9 May 2025 12:55:32 +0800 Subject: [PATCH 1/2] =?UTF-8?q?onScroll=20=E8=A7=A6=E5=8F=91=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E5=A2=9E=E5=8A=A0=E8=8A=82=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/virt-list/index.tsx | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/components/virt-list/index.tsx b/src/components/virt-list/index.tsx index 127202c..d77683a 100644 --- a/src/components/virt-list/index.tsx +++ b/src/components/virt-list/index.tsx @@ -407,22 +407,33 @@ function useVirtList>( } } + // 在组件或类顶部定义状态变量 + let isAtTop = false; + let isAtBottom = false; + const THROTTLE_DELAY = 200; + function judgePosition() { - // 使用2px作为误差范围 const threshold = Math.max(props.scrollDistance, 2); + const now = Date.now(); if (direction === 'forward') { - if (reactiveData.offset - threshold <= 0) { - // console.log('[VirtList] 到达顶部'); + const nearTop = reactiveData.offset - threshold <= 0; + if (nearTop && !isAtTop) { + isAtTop = true; emitFunction?.toTop?.(props.list[0]); + } else if (!nearTop) { + isAtTop = false; } } else if (direction === 'backward') { - // 使用一个 Math.round 来解决小数点的误差问题 const scrollSize = Math.round(reactiveData.offset + slotSize.clientSize); const distanceToBottom = Math.round(getTotalSize() - scrollSize); - if (distanceToBottom <= threshold) { - // console.log('[VirtList] 到达底部'); + const nearBottom = distanceToBottom <= threshold; + + if (nearBottom && !isAtBottom) { + isAtBottom = true; emitFunction?.toBottom?.(props.list[props.list.length - 1]); + } else if (!nearBottom) { + isAtBottom = false; } } } From a57087bbfb2d840ff66ef885567995b00eb1476b Mon Sep 17 00:00:00 2001 From: loyoi <1019748371@qq.com> Date: Sat, 24 May 2025 19:36:44 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=A7=A6=E5=BA=95?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E5=8F=AF=E8=83=BD=E8=A7=A6=E5=8F=91=E4=B8=A4?= =?UTF-8?q?=E6=AC=A1=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/virt-list/index.tsx | 41 ++++++++++++++---------------- src/components/virt-list/type.ts | 3 +++ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/components/virt-list/index.tsx b/src/components/virt-list/index.tsx index d77683a..05f1bf5 100644 --- a/src/components/virt-list/index.tsx +++ b/src/components/virt-list/index.tsx @@ -87,6 +87,9 @@ function useVirtList>( // 全局需要响应式的数据 const reactiveData: ShallowReactive = shallowReactive({ + hasReachedBottom: false, + hasReachedTop: false, + // 可视区域的个数,不算buffer,只和clientSize和minSize有关 views: 0, @@ -407,42 +410,35 @@ function useVirtList>( } } - // 在组件或类顶部定义状态变量 - let isAtTop = false; - let isAtBottom = false; - const THROTTLE_DELAY = 200; - function judgePosition() { const threshold = Math.max(props.scrollDistance, 2); - const now = Date.now(); if (direction === 'forward') { - const nearTop = reactiveData.offset - threshold <= 0; - if (nearTop && !isAtTop) { - isAtTop = true; - emitFunction?.toTop?.(props.list[0]); - } else if (!nearTop) { - isAtTop = false; + if (reactiveData.offset - threshold <= 0) { + if (!reactiveData.hasReachedTop) { + emitFunction?.toTop?.(props.list[0]); + reactiveData.hasReachedTop = true; + } + } else { + reactiveData.hasReachedTop = false; } } else if (direction === 'backward') { const scrollSize = Math.round(reactiveData.offset + slotSize.clientSize); const distanceToBottom = Math.round(getTotalSize() - scrollSize); - const nearBottom = distanceToBottom <= threshold; - if (nearBottom && !isAtBottom) { - isAtBottom = true; - emitFunction?.toBottom?.(props.list[props.list.length - 1]); - } else if (!nearBottom) { - isAtBottom = false; + if (distanceToBottom <= threshold) { + if (!reactiveData.hasReachedBottom) { + emitFunction?.toBottom?.(props.list[props.list.length - 1]); + reactiveData.hasReachedBottom = true; + } + } else { + reactiveData.hasReachedBottom = false; } } } function onScroll(evt: Event) { - // console.log('onscroll'); - emitFunction?.scroll?.(evt); - const offset = getOffset(); if (offset === reactiveData.offset) return; @@ -450,10 +446,11 @@ function useVirtList>( reactiveData.offset = offset; calcRange(); - judgePosition(); } + // const onScroll = throttledOnScroll; + function calcViews() { // 不算buffer的个数 const newViews = diff --git a/src/components/virt-list/type.ts b/src/components/virt-list/type.ts index 3568c79..7fae1cf 100644 --- a/src/components/virt-list/type.ts +++ b/src/components/virt-list/type.ts @@ -22,6 +22,9 @@ export type ReactiveData = { bufferTop: number; bufferBottom: number; + + hasReachedBottom: boolean; + hasReachedTop: boolean; }; export interface BaseListProps> {