From 38aeecfcb79e4b8fde488725dd74f381019cd417 Mon Sep 17 00:00:00 2001 From: neverland Date: Sat, 22 May 2021 17:38:05 +0800 Subject: [PATCH] fix(List): skip check when inside an inactive tab (#8741) --- src/composables/use-tab-status.ts | 8 ++++++++ src/list/List.tsx | 12 ++++++++++-- src/list/test/index.spec.js | 24 ++++++++++++++++++++++++ src/tab/Tab.tsx | 22 +++++++++++++--------- 4 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 src/composables/use-tab-status.ts diff --git a/src/composables/use-tab-status.ts b/src/composables/use-tab-status.ts new file mode 100644 index 000000000..319aa8f2c --- /dev/null +++ b/src/composables/use-tab-status.ts @@ -0,0 +1,8 @@ +import { inject, ComputedRef } from 'vue'; + +// eslint-disable-next-line +export const TAB_STATUS_KEY = Symbol(); + +export function useTabStatus() { + return inject | null>(TAB_STATUS_KEY, null); +} diff --git a/src/list/List.tsx b/src/list/List.tsx index cf941801a..447c271b9 100644 --- a/src/list/List.tsx +++ b/src/list/List.tsx @@ -14,6 +14,7 @@ import { isHidden, truthProp, createNamespace } from '../utils'; // Composables import { useRect, useScrollParent, useEventListener } from '@vant/use'; import { useExpose } from '../composables/use-expose'; +import { useTabStatus } from '../composables/use-tab-status'; // Components import { Loading } from '../loading'; @@ -50,11 +51,18 @@ export default defineComponent({ const loading = ref(false); const root = ref(); const placeholder = ref(); + const tabStatus = useTabStatus(); const scrollParent = useScrollParent(root); const check = () => { nextTick(() => { - if (loading.value || props.finished || props.error) { + if ( + loading.value || + props.finished || + props.error || + // skip check when inside an inactive tab + tabStatus?.value === false + ) { return; } @@ -62,7 +70,7 @@ export default defineComponent({ const scrollParentRect = useRect(scrollParent); if (!scrollParentRect.height || isHidden(root)) { - return false; + return; } let isReachEdge = false; diff --git a/src/list/test/index.spec.js b/src/list/test/index.spec.js index aa49d32c0..a53348019 100644 --- a/src/list/test/index.spec.js +++ b/src/list/test/index.spec.js @@ -1,4 +1,6 @@ import { List } from '..'; +import { Tab } from '../../tab'; +import { Tabs } from '../../tabs'; import { mount, later, mockGetBoundingClientRect } from '../../../test'; test('should emit load event when reaching bottom', async () => { @@ -134,3 +136,25 @@ test('should render correctly when direction is up', async () => { expect(children[0].classes()).toContain('list-item'); expect(children[1].classes()).toContain('van-list__placeholder'); }); + +test('should not emit load event when inside an inactive tab', async () => { + const onLoad1 = jest.fn(); + const onLoad2 = jest.fn(); + + mount({ + render: () => ( + + + + + + + + + ), + }); + + await later(); + expect(onLoad1).toHaveBeenCalledTimes(1); + expect(onLoad2).toHaveBeenCalledTimes(0); +}); diff --git a/src/tab/Tab.tsx b/src/tab/Tab.tsx index 54bc47906..b7e29c977 100644 --- a/src/tab/Tab.tsx +++ b/src/tab/Tab.tsx @@ -1,6 +1,8 @@ import { ref, watch, + provide, + computed, nextTick, PropType, CSSProperties, @@ -14,6 +16,7 @@ import { TABS_KEY, TabsProvide } from '../tabs/Tabs'; // Composables import { useParent } from '@vant/use'; import { routeProps } from '../composables/use-route'; +import { TAB_STATUS_KEY } from '../composables/use-tab-status'; // Components import { SwipeItem } from '../swipe-item'; @@ -56,15 +59,15 @@ export default defineComponent({ } }; - const isActive = () => { - const active = getName() === parent.currentName.value; + const active = computed(() => { + const isActive = getName() === parent.currentName.value; - if (active && !inited.value) { + if (isActive && !inited.value) { init(); } - return active; - }; + return isActive; + }); watch( () => props.title, @@ -74,6 +77,8 @@ export default defineComponent({ } ); + provide(TAB_STATUS_KEY, active); + return () => { const { animated, swipeable, scrollspy, lazyRender } = parent.props; @@ -81,15 +86,14 @@ export default defineComponent({ return; } - const active = isActive(); - const show = scrollspy || active; + const show = scrollspy || active.value; if (animated || swipeable) { return (
{slots.default?.()}