β¬ οΈ Back to Table of Contents
π useInfiniteScroll¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 2 |
| π¦ Imports | 16 |
| β‘ Async/Await Patterns | 2 |
| π’ Vue Composition API | 5 |
| π Interfaces | 2 |
| π Type Aliases | 1 |
π Table of Contents¶
π οΈ File Location:¶
π packages/core/useInfiniteScroll/index.ts
π¦ Imports¶
| Name | Source |
|---|---|
Awaitable |
@vueuse/shared |
ComputedRef |
vue |
MaybeRefOrGetter |
vue |
UnwrapNestedRefs |
vue |
UseScrollOptions |
../useScroll |
UseScrollReturn |
../useScroll |
tryOnUnmounted |
@vueuse/shared |
computed |
vue |
nextTick |
vue |
reactive |
vue |
shallowRef |
vue |
toValue |
vue |
watch |
vue |
resolveElement |
../_resolve-element |
useElementVisibility |
../useElementVisibility |
useScroll |
../useScroll |
Async/Await Patterns¶
| Type | Function | Await Expressions | Promise Chains |
|---|---|---|---|
| promise-chain | useInfiniteScroll |
none | Promise.all([ onLoadMore(state), new Promise(resolve => setTimeout(resolve, i... |
| promise-chain | checkAndLoad |
none | Promise.all([ onLoadMore(state), new Promise(resolve => setTimeout(resolve, i... |
Vue Composition API¶
| Name | Type | Reactive Variables | Composables |
|---|---|---|---|
reactive |
reactive | none | none |
computed |
computed | none | none |
computed |
computed | none | none |
computed |
computed | none | none |
watch |
watch | none | none |
Functions¶
useInfiniteScroll(element: MaybeRefOrGetter<T>, onLoadMore: (state: UnwrapNestedRefs<UseScrollReturβ¦, options: UseInfiniteScrollOptions<T>): UseInfiniteScrollReturn¶
Reactive infinite scroll.
See: https://vueuse.org/useInfiniteScroll
Calls:
reactive (from vue)useScroll (from ../useScroll)shallowRef (from vue)computed (from vue)resolveElement (from ../_resolve-element)toValue (from vue)useElementVisibility (from ../useElementVisibility)canLoadMorestate.measurePromise.all([ onLoadMore(state), new Promise(resolve => setTimeout(resolve, interval)), ]) .finallynextTick (from vue)checkAndLoadwatch (from vue)tryOnUnmounted (from @vueuse/shared)
Internal Comments:
Code
export function useInfiniteScroll<T extends InfiniteScrollElement>(
element: MaybeRefOrGetter<T>,
onLoadMore: (state: UnwrapNestedRefs<UseScrollReturn>) => Awaitable<void>,
options: UseInfiniteScrollOptions<T> = {},
): UseInfiniteScrollReturn {
const {
direction = 'bottom',
interval = 100,
canLoadMore = () => true,
} = options
const state = reactive(useScroll(
element,
{
...options,
offset: {
[direction]: options.distance ?? 0,
...options.offset,
},
},
))
const promise = shallowRef<Promise<unknown> | null>()
const isLoading = computed(() => !!promise.value)
// Document and Window cannot be observed by IntersectionObserver
const observedElement = computed<HTMLElement | SVGElement | null | undefined>(() => {
return resolveElement(toValue(element))
})
const isElementVisible = useElementVisibility(observedElement)
const canLoad = computed(() => {
if (!observedElement.value)
return false
return canLoadMore(observedElement.value as T)
})
function checkAndLoad() {
state.measure()
if (!observedElement.value || !isElementVisible.value || !canLoad.value || promise.value)
return
const { scrollHeight, clientHeight, scrollWidth, clientWidth } = observedElement.value as HTMLElement
const isNarrower = (direction === 'bottom' || direction === 'top')
? scrollHeight <= clientHeight
: scrollWidth <= clientWidth
if (state.arrivedState[direction] || isNarrower) {
promise.value = Promise.all([
onLoadMore(state),
new Promise(resolve => setTimeout(resolve, interval)),
])
.finally(() => {
promise.value = null
nextTick(() => checkAndLoad())
})
}
}
const stop = watch(
() => [state.arrivedState[direction], isElementVisible.value, canLoad.value],
checkAndLoad,
{ immediate: true, flush: 'post' },
)
tryOnUnmounted(stop)
return {
isLoading,
reset() {
nextTick(() => checkAndLoad())
},
}
}
Internal helpers¶
Declared inside another function in this file.
checkAndLoad(): void¶
Returns: void
Calls:
state.measurePromise.all([ onLoadMore(state), new Promise(resolve => setTimeout(resolve, interval)), ]) .finallynextTick (from vue)checkAndLoad
Code
function checkAndLoad() {
state.measure()
if (!observedElement.value || !isElementVisible.value || !canLoad.value || promise.value)
return
const { scrollHeight, clientHeight, scrollWidth, clientWidth } = observedElement.value as HTMLElement
const isNarrower = (direction === 'bottom' || direction === 'top')
? scrollHeight <= clientHeight
: scrollWidth <= clientWidth
if (state.arrivedState[direction] || isNarrower) {
promise.value = Promise.all([
onLoadMore(state),
new Promise(resolve => setTimeout(resolve, interval)),
])
.finally(() => {
promise.value = null
nextTick(() => checkAndLoad())
})
}
}
Interfaces¶
UseInfiniteScrollOptions<T extends InfiniteScrollElement = InfiniteScrollElement>¶
Interface Code
export interface UseInfiniteScrollOptions<T extends InfiniteScrollElement = InfiniteScrollElement> extends UseScrollOptions {
/**
* The minimum distance between the bottom of the element and the bottom of the viewport
*
* @default 0
*/
distance?: number
/**
* The direction in which to listen the scroll.
*
* @default 'bottom'
*/
direction?: 'top' | 'bottom' | 'left' | 'right'
/**
* The interval time between two load more (to avoid too many invokes).
*
* @default 100
*/
interval?: number
/**
* A function that determines whether more content can be loaded for a specific element.
* Should return `true` if loading more content is allowed for the given element,
* and `false` otherwise.
*/
canLoadMore?: (el: T) => boolean
}
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
distance |
number |
β | not shown |
direction |
'top' \| 'bottom' \| 'left' \| 'right' |
β | not shown |
interval |
number |
β | not shown |
canLoadMore |
(el: T) => boolean |
β | not shown |
UseInfiniteScrollReturn¶
Interface Code
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
isLoading |
ComputedRef<boolean> |
β | not shown |
reset |
() => void |
β | not shown |
Type Aliases¶
InfiniteScrollElement¶
Generated by Syntax Scribe