组件/VirtualList 虚拟列表

VirtualList 虚拟列表

只渲染可见行的固定行高长列表

已验证自 0.3.4

用法

基础

itemHeight 固定行高,height 设定视口高度。

示例加载中...

稳定的 key

<template>
  <TxVirtualList :items="users" :item-height="44" height="360px" item-key="id">
    <template #item="{ item }">
      <UserRow :user="item" />
    </template>
  </TxVirtualList>
</template>

命令式滚动

<script setup lang="ts">
const listRef = ref()

function jumpToLatest() {
  listRef.value?.scrollToBottom()
}
</script>

<template>
  <TxButton @click="jumpToLatest">最新</TxButton>
  <TxVirtualList ref="listRef" :items="logs" :item-height="32" :height="400" />
</template>

最佳实践

  • 只用于固定行高;变高内容会让滚动计算失真。
  • 对象列表用 itemKey 指向稳定 id;只有不可变数组才适合用索引作 key。
  • overscan 保持适中:越大快速滚动越平滑,DOM 开销也越大。
  • 行间距放进固定高度的行内,不要给行加垂直 margin。
  • scroll 只用于统计或懒加载触发,不要做逐帧重计算。

API 参考

属性

属性名类型默认值说明
itemsT[][]完整数据集。
itemHeightnumber必填固定行高(px),所有行必须一致。
heightnumber | string320滚动容器高度;数字转为 px。
overscannumber4视口前后额外渲染的行数。
itemKeykeyof T | (item: T, index: number) => string | numberindex行 key:字段名或函数;字段缺失时回退为该项在 items 中的索引。

事件

事件名参数说明
scroll{ scrollTop: number, startIndex: number, endIndex: number }滚动并更新可见区间后触发。

插槽

插槽名Props说明
item{ item: T, index: number }渲染每个可见项;默认把 item 渲染为文本。

暴露方法

方法签名说明
scrollToIndex(index: number) => void滚动到 Math.max(0, index) * itemHeight;不限制超出末项的索引。
scrollToTop() => void滚动到顶部。
scrollToBottom() => void滚动到 max(0, totalHeight - viewHeight)。

概述

  • 每行固定为 itemHeight 像素高;数字 height 转为 px,字符串原样应用。
  • 数字、px 与纯数字字符串高度立即参与计算;%、vh、vw、rem、em 等到挂载后读取 clientHeight,SSR 或隐藏容器应给出具体高度。
  • 存在 ResizeObserver 时,容器尺寸变化会更新视口高度。
  • 可见区间从 floor(scrollTop / itemHeight) - overscan 到视口末端再加 overscan,限制在 0 与 items.length 之间。
  • 占位高度为 items.length * itemHeight,可见项按 startIndex * itemHeight 位移。
  • 容器与行不带 role 或 aria-*。需要列表语义时由外层补 role="list" / role="listitem",aria-setsize / aria-posinset 使用真实总数与绝对索引。

技术实现

  • 源码:packages/tuffex/packages/components/src/virtual-list/。
查看源码
packages/tuffex/packages/components/src/virtual-list/index.ts