useVirtualList
警告
如果你需要更多功能,请考虑使用 vue-virtual-scroller
。
轻松创建虚拟列表。虚拟列表(有时也称为 虚拟滚动器)允许你高性能地渲染大量项目。它们通过使用 wrapper
元素来模拟 container
元素的完整高度,只渲染显示 container
元素中项目所需的最小 DOM 节点数量。
演示
跳到索引
按大小筛选列表
用法
简单列表
ts
import { useVirtualList } from '@vueuse/core'
const { list, containerProps, wrapperProps } = useVirtualList(
Array.from(Array.from({ length: 99999 }).keys()),
{
// Keep `itemHeight` in sync with the item's row.
itemHeight: 22,
},
)
配置
状态 | 类型 | 描述 |
---|---|---|
itemHeight | 数字 | 确保 wrapper 元素的总高度计算正确。* |
itemWidth | 数字 | 确保 wrapper 元素的总宽度计算正确。* |
overscan | 数字 | 预渲染的 DOM 节点数量。防止你快速滚动时项目之间出现空白。 |
* itemHeight
或 itemWidth
必须与渲染的每行高度保持同步。如果你在滚动到列表底部时看到额外的空白或抖动,请确保 itemHeight
或 itemWidth
与行高相同。
响应式列表
ts
import { useToggle, useVirtualList } from '@vueuse/core'
import { computed } from 'vue'
const [isEven, toggle] = useToggle()
const allItems = Array.from(Array.from({ length: 99999 }).keys())
const filteredList = computed(() => allItems.filter(i => isEven.value ? i % 2 === 0 : i % 2 === 1))
const { list, containerProps, wrapperProps } = useVirtualList(
filteredList,
{
itemHeight: 22,
},
)
vue
<template>
<p>Showing {{ isEven ? 'even' : 'odd' }} items</p>
<button @click="toggle">
Toggle Even/Odd
</button>
<div v-bind="containerProps" style="height: 300px">
<div v-bind="wrapperProps">
<div v-for="item in list" :key="item.index" style="height: 22px">
Row: {{ item.data }}
</div>
</div>
</div>
</template>
水平列表
ts
import { useVirtualList } from '@vueuse/core'
const allItems = Array.from(Array.from({ length: 99999 }).keys())
const { list, containerProps, wrapperProps } = useVirtualList(
allItems,
{
itemWidth: 200,
},
)
vue
<template>
<div v-bind="containerProps" style="height: 300px">
<div v-bind="wrapperProps">
<div v-for="item in list" :key="item.index" style="width: 200px">
Row: {{ item.data }}
</div>
</div>
</div>
</template>
组件用法
此函数还通过
@vueuse/components
包提供了一个无渲染组件版本。了解更多用法。
vue
<template>
<UseVirtualList :list="list" :options="options" height="300px">
<template #default="props">
<!-- you can get current item of list here -->
<div style="height: 22px">
Row {{ props.index }} {{ props.data }}
</div>
</template>
</UseVirtualList>
</template>
要滚动到特定元素,该组件公开了 scrollTo(index: number) => void
方法。
类型声明
显示类型声明
ts
type UseVirtualListItemSize = number | ((index: number) => number)
export interface UseHorizontalVirtualListOptions
extends UseVirtualListOptionsBase {
/**
* item width, accept a pixel value or a function that returns the width
*
* @default 0
*/
itemWidth: UseVirtualListItemSize
}
export interface UseVerticalVirtualListOptions
extends UseVirtualListOptionsBase {
/**
* item height, accept a pixel value or a function that returns the height
*
* @default 0
*/
itemHeight: UseVirtualListItemSize
}
export interface UseVirtualListOptionsBase {
/**
* the extra buffer items outside of the view area
*
* @default 5
*/
overscan?: number
}
export type UseVirtualListOptions =
| UseHorizontalVirtualListOptions
| UseVerticalVirtualListOptions
export interface UseVirtualListItem<T> {
data: T
index: number
}
export interface UseVirtualListReturn<T> {
list: Ref<UseVirtualListItem<T>[]>
scrollTo: (index: number) => void
containerProps: {
ref: Ref<HTMLElement | null>
onScroll: () => void
style: StyleValue
}
wrapperProps: ComputedRef<{
style:
| {
width: string
height: string
marginTop: string
}
| {
width: string
height: string
marginLeft: string
display: string
}
}>
}
/**
* Please consider using [`vue-virtual-scroller`](https://github.com/Akryum/vue-virtual-scroller) if you are looking for more features.
*/
export declare function useVirtualList<T = any>(
list: MaybeRef<readonly T[]>,
options: UseVirtualListOptions,
): UseVirtualListReturn<T>