import { ref, watch, nextTick, onUpdated, onMounted } from 'vue'; // Utils import { isHidden, createNamespace } from '../utils'; // Composition import { useRect, useScrollParent, useEventListener } from '@vant/use'; import { useExpose } from '../composition/use-expose'; // Components import Loading from '../loading'; const [createComponent, bem, t] = createNamespace('list'); export default createComponent({ props: { error: Boolean, loading: Boolean, finished: Boolean, errorText: String, loadingText: String, finishedText: String, immediateCheck: { type: Boolean, default: true, }, offset: { type: [Number, String], default: 300, }, direction: { type: String, default: 'down', }, }, emits: ['load', 'update:error', 'update:loading'], setup(props, { emit, slots }) { // use sync innerLoading state to avoid repeated loading in some edge cases const loading = ref(false); const root = ref(); const placeholder = ref(); const scrollParent = useScrollParent(root); const check = () => { nextTick(() => { if (loading.value || props.finished || props.error) { return; } const { offset, direction } = props; const scrollParentRect = useRect(scrollParent); if (!scrollParentRect.height || isHidden(root)) { return false; } let isReachEdge = false; const placeholderRect = useRect(placeholder); if (direction === 'up') { isReachEdge = scrollParentRect.top - placeholderRect.top <= offset; } else { isReachEdge = placeholderRect.bottom - scrollParentRect.bottom <= offset; } if (isReachEdge) { loading.value = true; emit('update:loading', true); emit('load'); } }); }; const renderFinishedText = () => { if (props.finished) { const text = slots.finished ? slots.finished() : props.finishedText; if (text) { return