Skip to content

VirtualList

Used for large data list rendering, solving issues with too many nodes and scroll lag. Fixed height is the primary path, dynamic height is an enhanced mode.

Note

This component is implemented based on the useVirtualWindow Hook, only rendering list items within the visible area, significantly improving rendering performance for large data lists.

Platform Differences

App (vue)App (nvue)H5Mini Program

Basic Usage

  • Pass data list via list.
  • Set item height (in px) via itemHeight.
  • Set viewport height via 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>

Dynamic Height

  • Set dynamic to true to enable dynamic height mode.
  • Set estimated height via 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>

Horizontal Scrolling

  • Set horizontal to true to enable horizontal scrolling mode.
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>

Item Gap

  • Set item gap (in px) via itemGap.
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

  • Set the number of buffer items above and below via buffer, defaults to 5.
  • A larger buffer reduces blank screen probability during scrolling but increases rendered nodes.
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>

Scroll to Position

  • Scroll to a specific index via scrollIntoIndex.
  • Use component instance methods scrollToIndex() or 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)">Go to #100</button>
<button @tap="listRef?.scrollToOffset(5000)">Go to offset 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)">Go to #100</button>
<button @tap="$refs.listRef.scrollToOffset(5000)">Go to offset 5000</button>

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

Load More

  • Set the distance threshold (in px) for triggering load more via lowerThreshold, defaults to 50.
  • Scrolling to the bottom triggers the onScrollToLower event.
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>

Slot Usage

  • header: List header slot.
  • footer: List footer slot.
  • item: List item slot, exposes item, index, activeIndex.
  • empty: Custom empty state.
html
<see-virtual-list :list="list" :itemHeight="50" height="400px">
  <template #header>
    <view style="padding: 20rpx; font-weight: bold;">Virtual List</view>
  </template>
  <template #item="{ item, index }">
    <view style="padding: 12rpx 24rpx;">{{ index }}. {{ item }}</view>
  </template>
  <template #footer>
    <view style="padding: 20rpx; text-align: center;">— End —</view>
  </template>
</see-virtual-list>

Custom Scrollbar

  • Set whether to show the scrollbar via showScrollbar, defaults to 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

ParameterDescriptionTypeDefaultOptional ValuesPlatform Notes
listData listArray[]Any array-
itemHeightItem height (px), required for fixed height modeNumber44Any positive number-
heightViewport heightNumber / String'100%'px value or CSS value-
keyFieldUnique identifier field nameString''Any string-
bufferNumber of buffer items above and belowNumber5Any positive number-
scrollTopInitial scroll offset (px), not yet effective, use scrollIntoIndex insteadNumber0Any non-negative number-
scrollIntoIndexScroll to specified indexNumberundefinedAny non-negative integer-
horizontalWhether to enable horizontal scrollingBooleanfalsetrue, false-
itemGapItem gap (px)Number0Any non-negative number-
estimatedItemHeightEstimated item height (px) for dynamic modeNumberundefinedAny positive number-
dynamicWhether to enable dynamic heightBooleanfalsetrue, false-
lowerThresholdDistance threshold to trigger load more (px)Number50Any positive number-
upperThresholdDistance threshold to trigger scroll to top (px)Number50Any positive number-
showScrollbarWhether to show scrollbarBooleantruetrue, false-

Events

EventDescriptionCallback ParametersPlatform Notes
onScrollTriggered on scroll{ scrollLeft, scrollTop, deltaX, deltaY }-
onRangeChangeTriggered on visible range change{ start, end, visibleStart, visibleEnd }-
onScrollToLowerTriggered when scrolling to bottomNone-
onScrollToUpperTriggered when scrolling to topNone-
onItemClickTriggered when list item is tappeditem: unknown, index: number-

Slots

Slot NameDescriptionScope Data
headerList headerNone
footerList footerNone
itemList item content{ item, index, activeIndex } (activeIndex is the visible area start index)
emptyCustom empty stateNone

Methods

Call via component instance obtained through ref.

MethodDescriptionParameters
scrollToIndexScroll to specified indexindex: number, animated?: boolean
scrollToOffsetScroll to specified offsetoffset: number, animated?: boolean
resetReset scroll positionNone

Liao ICP No. 2025070134