dynamic-height-virtual-list
v0.1.1
Published
A Vue 3 virtual scroll component supporting dynamic item heights
Maintainers
Readme
dynamic-height-virtual-list
一个 Vue 3 虚拟滚动组件,支持 不定高子元素动态测量,面向万级(10k-100k)数据量场景优化。
特性
- ✅ 虚拟滚动 — 仅渲染可视区域 + 缓冲区内的 DOM 节点,恒定 DOM 数量
- ✅ 不定高支持 — 通过 ResizeObserver 动态测量每项实际高度,无需固定 item 高度
- ✅ 高性能查找 — 二分查找 O(log n) 定位起始索引,万级数据无压力
- ✅ 滚动方向抽象 — 第一版支持纵向滚动,架构已预留横向扩展
- ✅ TypeScript — 完整类型声明,开发体验友好
- ✅ 多种引入方式 — ESM / CJS / UMD,支持
app.use()全局注册和按需导入
安装
npm install dynamic-height-virtual-list快速开始
全局注册
import { createApp } from 'vue'
import MyVirtualList from 'dynamic-height-virtual-list'
import 'dynamic-height-virtual-list/dist/style.css'
const app = createApp(App)
app.use(MyVirtualList)按需导入
<script setup>
import { VirtualList } from 'dynamic-height-virtual-list'
import 'dynamic-height-virtual-list/dist/style.css'
</script>
<template>
<VirtualList
:data="listData"
item-key="id"
:estimated-item-size="60"
:buffer="5"
>
<template #default="{ item, index }">
<div class="my-item">{{ item.name }}</div>
</template>
</VirtualList>
</template>API
Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| data | T[] | 必填 | 列表数据源 |
| itemKey | string \| ((item: T, index: number) => string \| number) | 必填 | 唯一标识字段名或生成函数 |
| estimatedItemSize | number | 50 | 预估项高度(未测量前使用,单位 px) |
| buffer | number | 5 | 可视范围外的缓冲项数 |
| direction | 'vertical' \| 'horizontal' | 'vertical' | 滚动方向 |
| scrollThrottle | number | 16 | 滚动事件节流间隔(ms) |
Events
| 事件 | 参数 | 说明 |
|------|------|------|
| scroll | { scrollOffset: number, startIndex: number, endIndex: number } | 滚动事件,返回当前偏移量和可见范围 |
Slots
| 插槽 | 作用域参数 | 说明 |
|------|------------|------|
| default | { item: T, index: number, style: CSSProperties } | 列表项内容 |
| header | — | 列表头部内容 |
| footer | — | 列表底部内容 |
核心算法
不定高虚拟滚动
- 位置数组:维护
positions[]数组,每项记录{ top, bottom, height },通过前缀和累加 - 二分查找:根据
scrollTop在positions[]中查找起始索引,O(log n) - 可视范围:从 startIndex 向下累加,直到
bottom > scrollTop + viewportHeight - 缓冲区:startIndex 向前、endIndex 向后各扩展 buffer 项
- ResizeObserver:动态测量每项实际高度,回调更新缓存并重算 positions
渲染结构
容器 (div, overflow:auto, 监听scroll)
├── 幽灵层 (div, 总高度占位, 撑起滚动条)
└── 内容层 (div, transform 偏移)
└── item (div, ResizeObserver 测量)
└── default slot架构
src/
├── components/
│ └── VirtualList.vue # 主组件
├── composables/
│ ├── useVirtualScroll.ts # 核心滚动计算
│ ├── useItemMeasure.ts # 尺寸测量
│ └── useScrollDirection.ts # 方向抽象
├── types/
│ └── index.ts # TypeScript 类型
├── utils/
│ └── binarySearch.ts # 二分查找
└── index.ts # 导出入口开发
# 安装依赖
npm install
# 启动 Demo 开发服务器
npm run dev
# 构建
npm run build
# 运行测试
npm run testLicense
MIT
