fix(List): skip check when inside an inactive tab (#8741)

This commit is contained in:
neverland 2021-05-22 17:38:05 +08:00 committed by GitHub
parent 62a30bbf02
commit 38aeecfcb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 11 deletions

View File

@ -0,0 +1,8 @@
import { inject, ComputedRef } from 'vue';
// eslint-disable-next-line
export const TAB_STATUS_KEY = Symbol();
export function useTabStatus() {
return inject<ComputedRef<boolean> | null>(TAB_STATUS_KEY, null);
}

View File

@ -14,6 +14,7 @@ import { isHidden, truthProp, createNamespace } from '../utils';
// Composables // Composables
import { useRect, useScrollParent, useEventListener } from '@vant/use'; import { useRect, useScrollParent, useEventListener } from '@vant/use';
import { useExpose } from '../composables/use-expose'; import { useExpose } from '../composables/use-expose';
import { useTabStatus } from '../composables/use-tab-status';
// Components // Components
import { Loading } from '../loading'; import { Loading } from '../loading';
@ -50,11 +51,18 @@ export default defineComponent({
const loading = ref(false); const loading = ref(false);
const root = ref<HTMLElement>(); const root = ref<HTMLElement>();
const placeholder = ref<HTMLElement>(); const placeholder = ref<HTMLElement>();
const tabStatus = useTabStatus();
const scrollParent = useScrollParent(root); const scrollParent = useScrollParent(root);
const check = () => { const check = () => {
nextTick(() => { 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; return;
} }
@ -62,7 +70,7 @@ export default defineComponent({
const scrollParentRect = useRect(scrollParent); const scrollParentRect = useRect(scrollParent);
if (!scrollParentRect.height || isHidden(root)) { if (!scrollParentRect.height || isHidden(root)) {
return false; return;
} }
let isReachEdge = false; let isReachEdge = false;

View File

@ -1,4 +1,6 @@
import { List } from '..'; import { List } from '..';
import { Tab } from '../../tab';
import { Tabs } from '../../tabs';
import { mount, later, mockGetBoundingClientRect } from '../../../test'; import { mount, later, mockGetBoundingClientRect } from '../../../test';
test('should emit load event when reaching bottom', async () => { 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[0].classes()).toContain('list-item');
expect(children[1].classes()).toContain('van-list__placeholder'); 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: () => (
<Tabs active={0} animated>
<Tab>
<List onLoad={onLoad1} />
</Tab>
<Tab>
<List onLoad={onLoad2} />
</Tab>
</Tabs>
),
});
await later();
expect(onLoad1).toHaveBeenCalledTimes(1);
expect(onLoad2).toHaveBeenCalledTimes(0);
});

View File

@ -1,6 +1,8 @@
import { import {
ref, ref,
watch, watch,
provide,
computed,
nextTick, nextTick,
PropType, PropType,
CSSProperties, CSSProperties,
@ -14,6 +16,7 @@ import { TABS_KEY, TabsProvide } from '../tabs/Tabs';
// Composables // Composables
import { useParent } from '@vant/use'; import { useParent } from '@vant/use';
import { routeProps } from '../composables/use-route'; import { routeProps } from '../composables/use-route';
import { TAB_STATUS_KEY } from '../composables/use-tab-status';
// Components // Components
import { SwipeItem } from '../swipe-item'; import { SwipeItem } from '../swipe-item';
@ -56,15 +59,15 @@ export default defineComponent({
} }
}; };
const isActive = () => { const active = computed(() => {
const active = getName() === parent.currentName.value; const isActive = getName() === parent.currentName.value;
if (active && !inited.value) { if (isActive && !inited.value) {
init(); init();
} }
return active; return isActive;
}; });
watch( watch(
() => props.title, () => props.title,
@ -74,6 +77,8 @@ export default defineComponent({
} }
); );
provide(TAB_STATUS_KEY, active);
return () => { return () => {
const { animated, swipeable, scrollspy, lazyRender } = parent.props; const { animated, swipeable, scrollspy, lazyRender } = parent.props;
@ -81,15 +86,14 @@ export default defineComponent({
return; return;
} }
const active = isActive(); const show = scrollspy || active.value;
const show = scrollspy || active;
if (animated || swipeable) { if (animated || swipeable) {
return ( return (
<SwipeItem <SwipeItem
role="tabpanel" role="tabpanel"
aria-hidden={!active} aria-hidden={!active.value}
class={bem('pane-wrapper', { inactive: !active })} class={bem('pane-wrapper', { inactive: !active.value })}
> >
<div class={bem('pane')}>{slots.default?.()}</div> <div class={bem('pane')}>{slots.default?.()}</div>
</SwipeItem> </SwipeItem>