@jason12306/vue-async-virtual-scroll
Version:
High-performance asynchronous virtual scroll component for Vue 3 with dynamic height support and optimized rendering for large datasets
195 lines (143 loc) • 6.31 kB
Markdown
# async-virtual-scroll - Vue3 Asynchronous Virtual Scroll Component
> High-performance virtual scroll component supporting dynamic height rendering, optimized for large data list display
[简体中文](https://github.com/Jason12306/vue-async-virtual-scroll/blob/main/README-ZH_CN.md)
[react version](https://github.com/Jason12306/react-async-virtual-scroll)
## Features
- 🚀 Efficient rendering of massive datasets
- 📏 Supports fixed height and dynamic height
- 🔍 Automatically calculates visible area content
- 🔄 Built-in scroll optimization and buffer mechanism
- ⏳ Smart loading state management
- 🔧 Highly customizable configuration
## Installation & Usage
### Install
```bash
npm install @jason12306/vue-async-virtual-scroll
```
### Basic Usage
```html
<template>
<div class="test-container">
<div class="scroll-container">
<async-virtual-scroll v-model="show" :data="items" :item-size="60">
<template v-slot="{ item, dataUid }">
<div class="list-item" :data-uid="dataUid" :style="{ backgroundColor: item.color }">
{{ item.id }}. {{ item.text }}
</div>
</template>
</async-virtual-scroll>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import AsyncVirtualScroll from '@jason12306/vue-async-virtual-scroll'
import '@jason12306/vue-async-virtual-scroll/vue-async-virtual-scroll.css'
const show = ref(false)
const num = 500
const items = ref([])
for (let i = 1; i <= num; i++) {
items.value.push({
id: i,
text: `Item ${i}`,
color: i % 2 ? '#e0f7fa' : '#fffde7',
})
}
onMounted(() => {
show.value = true
})
</script>
<style scoped>
.test-container {
padding: 20px;
}
.scroll-container {
height: 500px;
border: 1px solid #ddd;
overflow: auto;
}
.list-item {
height: 60px;
line-height: 60px;
padding: 0 16px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
</style>
```
## Props Configuration
| Name | Type | Required | Default | Description |
| ----------- | ------- | --------------------------- | ---------- | ------------------------------------------------------------------------ |
| v-model | Boolean | Yes | false | Controls whether virtual scrolling is enabled (must use v-model binding) |
| ban | Boolean | No | false | Disable virtual scrolling (for small datasets) |
| itemSize | Number | Required for fixed height | undefined | Item height in fixed-height mode (px) |
| minItemSize | Number | Required for dynamic height | undefined | Minimum item height in dynamic-height mode (px) |
| data | Array | Yes | [] | Data array to render |
| buffer | Array | No | [200, 200] | Buffer zone sizes [top buffer, bottom buffer] (px) |
| keyField | String | No | 'id' | Field name for unique identifier in data items |
| dataUid | String | No | 'data-uid' | DOM attribute name for storing data unique identifier |
| viewNum | Number | No | 1 | Minimum number of items visible initially (for estimation) |
## Slots
### default
Main rendering slot for defining each item's content
#### Slot Parameters
| Parameter | Type | Description |
| --------- | ------ | ---------------------- |
| item | Object | Current data item |
| index | Number | Item index in data |
| dataUid | String | Item unique identifier |
## Usage Scenarios
### 1. Fixed Height Mode
When all items have the same height, use fixed height mode for optimal performance:
```html
<async-virtual-scroll v-model="enabled" :data="largeList" :item-size="60">
<!-- template content -->
</async-virtual-scroll>
```
### 2. Dynamic Height Mode
When items have varying heights, use dynamic height mode:
```html
<async-virtual-scroll v-model="enabled" :data="varyingHeightList" :min-item-size="40">
<!-- template content -->
</async-virtual-scroll>
```
### 3. Disable Virtual Scrolling
Disable virtual scrolling for small datasets:
```html
<async-virtual-scroll :data="list" :ban="list.length < 100">
<!-- template content -->
</async-virtual-scroll>
```
### 4. Custom Buffer Zone
Adjust buffer sizes as needed:
```html
<async-virtual-scroll :data="list" :buffer="[150, 300]">
<!-- template content -->
</async-virtual-scroll>
```
## Important Notes
1. **Must bind v-model**
2. **Dynamic Height Mode Requirements**
- Must provide `minItemSize` property for initial height estimation
- Component automatically detects and updates layout when item heights change
3. **Performance Optimization Suggestions**
- Prefer `itemSize` for fixed-height items
- Set appropriate `buffer` values to balance performance and UX
- Avoid complex computations in item templates
4. **Data Updates**
- Layout automatically updates when data changes
- Render area automatically adjusts for significant data changes
## Why?
Traditional rendering methods create all DOM elements at once for large datasets, causing:
1. **High Memory Usage**: Thousands of DOM nodes consume significant memory
2. **Reduced Rendering Performance**: Browser handles excessive layout and paint operations
3. **Interaction Lag**: Noticeable stuttering during scrolling and user interactions
**Asynchronous Virtual Scrolling** solves these issues by:
- 🚀 **On-demand Rendering**: Only renders elements in viewport
- ⏱ **Deferred Calculation**: Uses IntersectionObserver for async visibility detection
- 🔄 **Smart Buffering**: Preloads elements outside viewport for smooth scrolling
- 📊 **Height Caching**: Records rendered element heights to avoid recalculation
## Demo
https://github.com/user-attachments/assets/b84d2e26-de03-4e89-8f81-c0abb02aa8cc
## License
MIT License