Skip to content

InfiniteScroll ​

Automatically load more data when scrolling to the bottom. Uses IntersectionObserver for efficient scroll detection.

Preview ​

Preview
已加载:10 / 25
数据项 1
数据项 2
数据项 3
数据项 4
数据项 5
数据项 6
数据项 7
数据项 8
数据项 9
数据项 10

Installation ​

pnpm dlx brutx-vue@latest add infinite-scroll

Usage ​

vue
<script setup>
import { ref } from 'vue'
import { InfiniteScroll } from 'brutx-ui-vue'

const items = ref(Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`))
const loading = ref(false)

async function loadMore() {
    loading.value = true
    // Simulate API call
    await new Promise(resolve => setTimeout(resolve, 1000))
    const newItems = Array.from(
        { length: 10 },
        (_, i) => `Item ${items.value.length + i + 1}`
    )
    items.value.push(...newItems)
    loading.value = false
}
</script>

<template>
    <InfiniteScroll @load="loadMore">
        <div v-for="item in items" :key="item" class="p-4 border-b">
            {{ item }}
        </div>
    </InfiniteScroll>
</template>

With Custom Loading ​

vue
<script setup>
import { ref } from 'vue'
import { InfiniteScroll, Spinner } from 'brutx-ui-vue'

const items = ref([])

async function loadMore() {
    // Load data
}
</script>

<template>
    <InfiniteScroll @load="loadMore">
        <div v-for="item in items" :key="item.id">
            {{ item.name }}
        </div>

        <template #loading>
            <div class="flex items-center justify-center py-4">
                <Spinner size="sm" />
                <span class="ml-2">Loading more...</span>
            </div>
        </template>
    </InfiniteScroll>
</template>

Disabled State ​

vue
<script setup>
import { ref } from 'vue'
import { InfiniteScroll } from 'brutx-ui-vue'

const items = ref([])
const hasMore = ref(true)

async function loadMore() {
    if (!hasMore.value) return
    // Load data...
    // If no more data:
    // hasMore.value = false
}
</script>

<template>
    <InfiniteScroll :disabled="!hasMore" @load="loadMore">
        <div v-for="item in items" :key="item.id">
            {{ item.name }}
        </div>
    </InfiniteScroll>
</template>

API Reference ​

InfiniteScroll — Props
NameTypeDefaultDescription
distance
number | undefined
100
The number of pixels by which the intersection observer trigger area expands beyond the viewport.
Details

Declared type

number | undefined

Default value details

Resolved value
100

Source

InfiniteScroll.vue:9

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

delay
number | undefined
200
The debounce delay in milliseconds after the loading sentinel enters the trigger area.
Details

Declared type

number | undefined

Default value details

Resolved value
200

Source

InfiniteScroll.vue:11

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

disabled
boolean | undefined
false
Disables load detection and disconnects the observer; loading is not triggered while disabled.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

InfiniteScroll.vue:13

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

immediate
boolean | undefined
true
Requests a load on mount and after re-enabling when true; when false, loading is triggered only by the sentinel entering the expanded viewport.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
true

Source

InfiniteScroll.vue:15

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

class
string | undefined
undefined
CSS classes added to the outer container for the list, loading state, and observer sentinel.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

InfiniteScroll.vue:16

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

InfiniteScroll — Events
NameSignature or typeDescription
@load
[]
Emitted without a payload when more data should load after the debounce delay. Call resetLoading() after the parent finishes loading.
Details

Declared type

[]

Source

InfiniteScroll.vue

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

InfiniteScroll — Slots
NameSignature or typeDescription
#default
{}
The list or scrolling content to extend as more data is loaded.
Details

Declared type

{}

Source

InfiniteScroll.vue

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

#loading
{}
A custom indicator shown while a load is in progress; pulsing dots are shown when omitted.
Details

Declared type

{}

Source

InfiniteScroll.vue

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

InfiniteScroll — Exposes
NameSignature or typeDescription
resetLoading
() => void
Marks loading as complete and checks the sentinel again. If it remains inside the expanded viewport, another load may fire immediately; set disabled to true when no more data is available.
Details

Declared type

() => void

Source

InfiniteScroll.vue:184

packages/ui/src/components/infinite-scroll/InfiniteScroll.vue

Composable ​

For more flexible usage, use the useInfiniteScroll composable:

vue
<script setup>
import { ref } from 'vue'
import { useInfiniteScroll } from 'brutx-ui-vue'

const containerRef = ref(null)
const items = ref([])

const { isLoading, resetLoading } = useInfiniteScroll(containerRef, {
    distance: 100,
    delay: 200,
    onLoad: async () => {
        // Load data
        const newItems = await fetchItems()
        items.value.push(...newItems)
        resetLoading()
    },
})
</script>

<template>
    <div ref="containerRef">
        <div v-for="item in items" :key="item.id">
            {{ item.name }}
        </div>
    </div>
</template>

useInfiniteScroll Options ​

OptionTypeDefaultDescription
distancenumber100Trigger distance threshold in pixels
delaynumber200Debounce delay in milliseconds
disabledbooleanfalseWhether disabled
immediatebooleantrueWhether to check immediately on mount
onLoad() => void— (required)Load callback

useInfiniteScroll Returns ​

PropertyTypeDescription
isLoadingRef<boolean>Whether currently loading
resetLoading() => voidReset loading state

Accessibility ​

  • Screen Readers: Loading state is announced
  • Reduced Motion: Loading animation respects prefers-reduced-motion

Brute force builds.