@mikestools/usevirtualscroll
v0.0.2
Published
Vue 3 composable for virtual scrolling with pagination powered by usePagination
Maintainers
Readme
@mikestools/usevirtualscroll
Vue 3 composable for high-performance virtual scrolling with built-in pagination powered by usePagination from @mikestools/usetools.
Features
- ⚡ Virtual Scrolling - Only renders visible items for maximum performance
- 📄 Built-in Pagination - Uses
usePaginationfor robust pagination management - 🎯 Smart Buffer - Configurable buffer for smooth scroll experience
- 📍 Scroll-to-Index - Jump to any item instantly (auto-changes page)
- 🔄 Reactive - Automatically handles item changes with auto-reset
- 📏 Dynamic Page Size - Change page size at runtime
- 🧭 Full Navigation - First, last, next, previous, and direct page access
- 🧹 Auto-Cleanup - Cleans up listeners on unmount
- 🔒 TypeScript - Full type support with strict types
- 📦 Minimal Dependencies - Only requires Vue 3 and @mikestools/usetools
Installation
npm install @mikestools/usevirtualscroll @mikestools/usetools vueQuick Start
import { ref } from 'vue'
import { useVirtualScroll } from '@mikestools/usevirtualscroll'
const items = ref(Array.from({ length: 10000 }, (_, i) => ({
id: i + 1,
name: `Item ${i + 1}`
})))
const {
containerRef,
visibleItems,
totalHeight,
offsetY,
currentPage,
pageSize,
totalPages,
visiblePages,
hasPrevious,
hasNext,
goToPage,
nextPage,
previousPage,
setPageSize
} = useVirtualScroll({
items,
itemHeight: 50,
containerHeight: 400,
pageSize: 50
})API Reference
Options
| Option | Type | Default | Description |
|--------------------|------------|----------|--------------------------------------------------------|
| items | Ref<T[]> | required | Source data array |
| itemHeight | number | required | Fixed height of each item (px) |
| containerHeight | number | 600 | Container height (px) |
| pageSize | number | 20 | Items per page |
| bufferSize | number | 3 | Extra items to render outside viewport |
| autoReset | boolean | true | Auto-reset when items change and page is out of bounds |
| visiblePageCount | number | 5 | Number of page buttons to show |
| initialPage | number | 1 | Initial page to start on |
Return Values
Lifecycle State
| Property | Type | Description |
|-----------------|----------------------------|------------------------------------|
| isInitialized | Readonly<Ref<boolean>> | Whether composable has initialized |
| containerRef | Ref<HTMLElement \| null> | Attach to scroll container |
Item State
| Property | Type | Description |
|----------------|-----------------------|---------------------------|
| totalItems | ComputedRef<number> | Total items in source |
| pageItems | ComputedRef<T[]> | All items on current page |
| visibleItems | ComputedRef<T[]> | Items to render |
Virtual Scroll State
| Property | Type | Description |
|----------------|-----------------------|-----------------------------|
| totalHeight | ComputedRef<number> | Virtual content height (px) |
| offsetY | ComputedRef<number> | Y offset for positioning |
| visibleStart | ComputedRef<number> | First visible index |
| visibleEnd | ComputedRef<number> | Last visible index |
Pagination State (from usePagination)
| Property | Type | Description |
|----------------|-------------------------|------------------------------------|
| currentPage | Ref<number> | Current page (1-indexed, writable) |
| pageSize | Ref<number> | Items per page (writable) |
| totalPages | ComputedRef<number> | Total page count |
| visiblePages | ComputedRef<number[]> | Page numbers for UI |
| startIndex | ComputedRef<number> | Page start index (0-indexed) |
| endIndex | ComputedRef<number> | Page end index (exclusive) |
| hasPrevious | ComputedRef<boolean> | Has previous page |
| hasNext | ComputedRef<boolean> | Has next page |
| isFirstPage | ComputedRef<boolean> | On first page |
| isLastPage | ComputedRef<boolean> | On last page |
Methods
| Method | Returns | Description |
|------------------------|---------|-------------------------------------|
| goToPage(page) | void | Navigate to page (1-indexed) |
| nextPage() | void | Go to next page |
| previousPage() | void | Go to previous page |
| goToFirstPage() | void | Go to first page |
| goToLastPage() | void | Go to last page |
| reset() | void | Reset to page 1 |
| setPageSize(size) | void | Change page size (resets to page 1) |
| scrollToIndex(index) | void | Scroll to item by index |
| destroy() | void | Clean up resources |
Examples
Basic Virtual List
<template>
<div ref="containerRef" style="height: 400px; overflow: auto;">
<div :style="{ height: `${totalHeight}px`, position: 'relative' }">
<div :style="{ transform: `translateY(${offsetY}px)` }">
<div
v-for="item in visibleItems"
:key="item.id"
style="height: 50px;"
>
{{ item.name }}
</div>
</div>
</div>
</div>
<nav>
<button :disabled="!hasPrevious" @click="previousPage">Previous</button>
<button
v-for="page in visiblePages"
:key="page"
:class="{ active: page === currentPage }"
@click="goToPage(page)"
>
{{ page }}
</button>
<button :disabled="!hasNext" @click="nextPage">Next</button>
</nav>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useVirtualScroll } from '@mikestools/usevirtualscroll'
const items = ref(Array.from({ length: 10000 }, (_, i) => ({
id: i,
name: `Item ${i + 1}`
})))
const {
containerRef,
visibleItems,
totalHeight,
offsetY,
currentPage,
visiblePages,
hasPrevious,
hasNext,
previousPage,
nextPage,
goToPage
} = useVirtualScroll({
items,
itemHeight: 50,
containerHeight: 400,
pageSize: 100
})
</script>Scroll to Specific Item
const { scrollToIndex } = useVirtualScroll({ items, itemHeight: 50 })
// Jump to item at index 500 (changes page automatically)
scrollToIndex(500)Large Datasets (100K+ items)
const items = ref(generateItems(100000))
const {
visibleItems, // Only ~20 items rendered at a time
totalPages // 1000 pages at pageSize: 100
} = useVirtualScroll({
items,
itemHeight: 50,
pageSize: 100
})How It Works
- Pagination: Items split into pages (e.g., 50 items per page)
- Virtual Scroll: Within each page, only visible items rendered
- Buffer: Extra items above/below viewport for smooth scrolling
- Combined: Compact UI + high performance
Source Items: 10,000
↓
Pagination: Page 5 → Items 200-249 (50 items)
↓
Virtual Scroll: Items 210-225 visible
↓
DOM: Only 21 elements rendered (visible + buffer)Browser Support
| Browser | Minimum Version | |---------|-----------------| | Chrome | 80+ | | Firefox | 74+ | | Safari | 13.1+ | | Edge | 80+ |
License
MIT
