Skip to content

VirtualList 虚拟列表

用于大数据列表渲染,解决节点过多、滚动卡顿问题。固定高度是主路径,动态高度是增强模式。

说明

该组件基于 useVirtualWindow Hook 实现,仅渲染可视区域内的列表项,大幅提升大数据列表的渲染性能。

平台差异说明

App(vue)App(nvue)H5小程序

基本使用

  • 通过 list 传入数据列表。
  • 通过 itemHeight 设置列表项高度(px)。
  • 通过 height 设置可视区域高度。
html
<see-virtual-list :list="list" :itemHeight="50" height="400px">
  <template #item="{ item, index }">
    <view style="padding: 12rpx 24rpx;">{{ index }}. {{ item }}</view>
  </template>
</see-virtual-list>

<script lang="ts" setup>
const list = Array.from({ length: 10000 }, (_, i) => `Item ${i + 1}`)
</script>

动态高度

  • 设置 dynamictrue 开启动态高度模式。
  • 通过 estimatedItemHeight 设置预估高度。
html
<see-virtual-list
  :list="list"
  :itemHeight="50"
  :estimatedItemHeight="80"
  dynamic
  height="400px"
>
  <template #item="{ item }">
    <view style="padding: 16rpx 24rpx;">
      <text style="font-weight: bold;">{{ item.title }}</text>
      <text style="display: block; margin-top: 8rpx;">{{ item.content }}</text>
    </view>
  </template>
</see-virtual-list>

水平滚动

  • 设置 horizontaltrue 开启水平滚动模式。
html
<see-virtual-list
  :list="list"
  :itemHeight="200"
  height="240px"
  horizontal
>
  <template #item="{ item }">
    <view style="width: 200rpx; padding: 16rpx;">
      <image :src="item.image" style="width: 100%; height: 160rpx;" />
      <text>{{ item.name }}</text>
    </view>
  </template>
</see-virtual-list>

列表项间距

  • 通过 itemGap 设置列表项间距(px)。
html
<see-virtual-list :list="list" :itemHeight="50" :itemGap="8" height="400px">
  <template #item="{ item }">
    <view style="padding: 12rpx 24rpx; background: #f5f5f5; border-radius: 8rpx;">{{ item }}</view>
  </template>
</see-virtual-list>

缓冲区

  • 通过 buffer 设置上下缓冲项目数,默认为 5
  • 缓冲区越大,滚动时白屏概率越小,但渲染节点越多。
html
<see-virtual-list :list="list" :itemHeight="50" :buffer="10" height="400px">
  <template #item="{ item }">
    <view style="padding: 12rpx 24rpx;">{{ item }}</view>
  </template>
</see-virtual-list>

滚动到指定位置

  • 通过 scrollIntoIndex 滚动到指定索引。
  • 通过组件实例调用 scrollToIndex()scrollToOffset() 方法。
vue
<see-virtual-list
  ref="listRef"
  :list="list"
  :itemHeight="50"
  :scrollIntoIndex="scrollToIdx"
  height="400px"
>
  <template #item="{ item }">
    <view style="padding: 12rpx 24rpx;">{{ item }}</view>
  </template>
</see-virtual-list>
<button @tap="listRef?.scrollToIndex(100)">跳转到第100项</button>
<button @tap="listRef?.scrollToOffset(5000)">跳转到偏移量5000</button>

<script lang="ts" setup>
import { ref } from 'vue'
const listRef = ref()
const scrollToIdx = ref(0)
</script>
vue
<see-virtual-list
  ref="listRef"
  :list="list"
  :itemHeight="50"
  height="400px"
>
  <template #item="{ item }">
    <view style="padding: 12rpx 24rpx;">{{ item }}</view>
  </template>
</see-virtual-list>
<button @tap="$refs.listRef.scrollToIndex(100)">跳转到第100项</button>
<button @tap="$refs.listRef.scrollToOffset(5000)">跳转到偏移量5000</button>

<script>
export default {
  data() {
    return {}
  }
}
</script>

加载更多

  • 通过 lowerThreshold 设置触发加载更多的距离阈值(px),默认为 50
  • 滚动到底部触发 onScrollToLower 事件。
html
<see-virtual-list
  :list="list"
  :itemHeight="50"
  :lowerThreshold="100"
  height="400px"
  @onScrollToLower="loadMore"
>
  <template #item="{ item }">
    <view style="padding: 12rpx 24rpx;">{{ item }}</view>
  </template>
</see-virtual-list>

插槽用法

  • header:列表头部插槽。
  • footer:列表尾部插槽。
  • item:列表项插槽,暴露 itemindexactiveIndex
  • empty:自定义空状态。
html
<see-virtual-list :list="list" :itemHeight="50" height="400px">
  <template #header>
    <view style="padding: 20rpx; font-weight: bold;">虚拟列表</view>
  </template>
  <template #item="{ item, index }">
    <view style="padding: 12rpx 24rpx;">{{ index }}. {{ item }}</view>
  </template>
  <template #footer>
    <view style="padding: 20rpx; text-align: center;">— 到底了 —</view>
  </template>
</see-virtual-list>

自定义滚动条

  • 通过 showScrollbar 设置是否显示滚动条,默认为 true
html
<see-virtual-list :list="list" :itemHeight="50" :showScrollbar="false" height="400px">
  <template #item="{ item }">
    <view style="padding: 12rpx 24rpx;">{{ item }}</view>
  </template>
</see-virtual-list>

API

Props

参数名说明类型默认值可选值平台差异
list数据列表Array[]任意数组-
itemHeight列表项高度(px),固定高度模式必填Number44任意正数-
height可视区域高度Number / String'100%'px 数值或 CSS 值-
keyField唯一标识字段名String''任意字符串-
buffer上下缓冲项目数Number5任意正数-
scrollTop初始滚动偏移量(px),暂未生效,建议使用 scrollIntoIndexNumber0任意非负数-
scrollIntoIndex跳转到指定索引Numberundefined任意非负整数-
horizontal是否横向滚动Booleanfalsetruefalse-
itemGap列表项间距(px)Number0任意非负数-
estimatedItemHeight预估列表项高度(px),动态高度模式使用Numberundefined任意正数-
dynamic是否启用动态高度Booleanfalsetruefalse-
lowerThreshold触发加载更多的距离阈值(px)Number50任意正数-
upperThreshold触发加载更少的距离阈值(px)Number50任意正数-
showScrollbar是否显示滚动条Booleantruetruefalse-

Events

事件名说明回调参数平台差异
onScroll滚动时触发{ scrollLeft, scrollTop, deltaX, deltaY }-
onRangeChange可视范围变更时触发{ start, end, visibleStart, visibleEnd }-
onScrollToLower滚动到底部触发-
onScrollToUpper滚动到顶部触发-
onItemClick点击列表项触发item: unknown, index: number-

Slots

插槽名说明作用域数据
header列表头部
footer列表尾部
item列表项内容{ item, index, activeIndex }(activeIndex 为可视区域起始索引)
empty自定义空状态

Methods

通过 ref 获取组件实例后调用。

方法名说明参数
scrollToIndex滚动到指定索引index: number, animated?: boolean
scrollToOffset滚动到指定偏移量offset: number, animated?: boolean
reset重置滚动位置

辽 ICP 备 2025070134 号