From 185541f711340e88bf8909084071c4227676fc0e Mon Sep 17 00:00:00 2001 From: sallerli1 Date: Mon, 19 Sep 2022 09:57:05 +0800 Subject: [PATCH] fix(cdk:scroll): virtual scroll scrolledBottom event scrolledBottom event shouldn't trigger when maxheight change --- .../cdk/scroll/src/virtual/VirtualScroll.tsx | 3 +- .../virtual/composables/useScrollPlacement.ts | 36 ++++++++++--------- .../src/virtual/composables/useScrollTo.ts | 4 +-- .../scroll/src/virtual/contents/Holder.tsx | 12 +------ packages/cdk/scroll/src/virtual/token.ts | 1 + 5 files changed, 25 insertions(+), 31 deletions(-) diff --git a/packages/cdk/scroll/src/virtual/VirtualScroll.tsx b/packages/cdk/scroll/src/virtual/VirtualScroll.tsx index b307f2011..6abdb8be1 100644 --- a/packages/cdk/scroll/src/virtual/VirtualScroll.tsx +++ b/packages/cdk/scroll/src/virtual/VirtualScroll.tsx @@ -46,7 +46,7 @@ export default defineComponent({ heights, ) - const { syncScrollTop } = useScrollPlacement( + const { syncScrollTop, handleScroll } = useScrollPlacement( props, holderRef, scrollTop, @@ -66,6 +66,7 @@ export default defineComponent({ scrollHeight, scrollOffset, syncScrollTop, + handleScroll, }) const scrollTo = useScrollTo(props, holderRef, getKey, heights, collectHeights, syncScrollTop) diff --git a/packages/cdk/scroll/src/virtual/composables/useScrollPlacement.ts b/packages/cdk/scroll/src/virtual/composables/useScrollPlacement.ts index b70dc7ef7..348ca9690 100644 --- a/packages/cdk/scroll/src/virtual/composables/useScrollPlacement.ts +++ b/packages/cdk/scroll/src/virtual/composables/useScrollPlacement.ts @@ -6,20 +6,19 @@ */ import type { VirtualScrollProps } from '../types' -import type { ComputedRef, Ref } from 'vue' +import type { Ref } from 'vue' -import { computed, watchEffect } from 'vue' +import { computed } from 'vue' import { isFunction } from 'lodash-es' import { callEmit } from '@idux/cdk/utils' -export type SyncScrollTop = (newTop: number | ((prev: number) => number)) => void +export type SyncScrollTop = (newTop: number | ((prev: number) => number), setHolderScrollTop?: boolean) => void export interface ScrollPlacementContext { - scrolledTop: ComputedRef - scrolledBottom: ComputedRef syncScrollTop: SyncScrollTop + handleScroll: (evt: Event) => void } const keepInRange = (maxScrollHeight: number, newScrollTop: number) => { @@ -43,24 +42,27 @@ export function useScrollPlacement( return height > 0 ? Math.max(height - containerHeight.value, 0) : NaN }) - const scrolledTop = computed(() => scrollTop.value <= 0) - const scrolledBottom = computed(() => scrollTop.value >= maxScrollHeight.value) - - watchEffect(() => { - if (scrolledBottom.value) { - callEmit(props.onScrolledBottom) - } - }) - - const syncScrollTop = (newTop: number | ((prev: number) => number)) => { + const syncScrollTop = (newTop: number | ((prev: number) => number), setHolderScrollTop?: boolean) => { const value = isFunction(newTop) ? newTop(scrollTop.value) : newTop const alignedTop = keepInRange(maxScrollHeight.value, value) const holderElement = holderRef.value - if (holderElement) { + if (holderElement && setHolderScrollTop) { holderElement.scrollTop = alignedTop } changeScrollTop(alignedTop) } - return { scrolledTop, scrolledBottom, syncScrollTop } + const handleScroll = (evt: Event) => { + const { scrollTop: newScrollTop } = evt.currentTarget as Element + if (newScrollTop !== scrollTop.value) { + syncScrollTop(newScrollTop) + } + callEmit(props.onScroll, evt) + + if (newScrollTop >= maxScrollHeight.value) { + callEmit(props.onScrolledBottom) + } + } + + return { syncScrollTop, handleScroll } } diff --git a/packages/cdk/scroll/src/virtual/composables/useScrollTo.ts b/packages/cdk/scroll/src/virtual/composables/useScrollTo.ts index 50cea6ad2..8fd2ffcf1 100644 --- a/packages/cdk/scroll/src/virtual/composables/useScrollTo.ts +++ b/packages/cdk/scroll/src/virtual/composables/useScrollTo.ts @@ -36,7 +36,7 @@ export function useScrollTo( const { dataSource, itemHeight } = props if (typeof option === 'number') { - syncScrollTop(option) + syncScrollTop(option, true) } else if (typeof option === 'object') { const { align, offset = 0 } = option let index: number @@ -102,7 +102,7 @@ export function useScrollTo( } if (targetTop !== null && targetTop !== holderElement.scrollTop) { - syncScrollTop(targetTop) + syncScrollTop(targetTop, true) } } diff --git a/packages/cdk/scroll/src/virtual/contents/Holder.tsx b/packages/cdk/scroll/src/virtual/contents/Holder.tsx index 61953d81c..625d765ef 100644 --- a/packages/cdk/scroll/src/virtual/contents/Holder.tsx +++ b/packages/cdk/scroll/src/virtual/contents/Holder.tsx @@ -10,7 +10,6 @@ import { type CSSProperties, computed, defineComponent, inject, onBeforeUnmount, import { isString, throttle } from 'lodash-es' import { offResize, onResize } from '@idux/cdk/resize' -import { callEmit } from '@idux/cdk/utils' import { virtualScrollToken } from '../token' @@ -24,8 +23,7 @@ export default defineComponent({ collectHeights, scrollHeight, scrollOffset, - scrollTop, - syncScrollTop, + handleScroll, } = inject(virtualScrollToken)! const style = computed(() => { @@ -68,14 +66,6 @@ export default defineComponent({ } }) - const handleScroll = (evt: Event) => { - const { scrollTop: newScrollTop } = evt.currentTarget as Element - if (newScrollTop !== scrollTop.value) { - syncScrollTop(newScrollTop) - } - callEmit(props.onScroll, evt) - } - const contentRef = ref() const onContentResize = throttle(collectHeights, 16) // 这里不能用 useResizeObserver, 会有 test 爆栈警告, 具体原因后面再排查。 diff --git a/packages/cdk/scroll/src/virtual/token.ts b/packages/cdk/scroll/src/virtual/token.ts index b48f148c5..e93f3e676 100644 --- a/packages/cdk/scroll/src/virtual/token.ts +++ b/packages/cdk/scroll/src/virtual/token.ts @@ -20,6 +20,7 @@ export interface VirtualScrollContext { scrollHeight: Ref scrollOffset: Ref syncScrollTop: SyncScrollTop + handleScroll: (evt: Event) => void } export const virtualScrollToken: InjectionKey = Symbol('virtualScrollToken')