INFO
如果您正在寻找更多功能,请使用vue-virtual-scroller
INFO
Please consider using vue-virtual-scroller
if you are looking for more features.
useVirtualList
轻松创建虚拟列表。虚拟列表(有时称为virtual scrollers)允许您高效地呈现大量的项。通过使用 wrapper
元素来模拟容器的完整高度,只呈现最少数量的DOM节点来显示 container
元素中的项。
Create virtual lists with ease. Virtual lists (sometimes called virtual scrollers) allow you to render a large number of items performantly. They only render the minimum number of DOM nodes necessary to show the items within the container
element by using the wrapper
element to emulate the container element's full height.
例子
Usage
Simple list
import { useVirtualList } from '@vueuse/core'
const { list, containerProps, wrapperProps } = useVirtualList(
Array.from(Array(99999).keys()),
{
// Keep `itemHeight` in sync with the item's row.
itemHeight: 22,
},
)
import { useVirtualList } from '@vueuse/core'
const { list, containerProps, wrapperProps } = useVirtualList(
Array.from(Array(99999).keys()),
{
// Keep `itemHeight` in sync with the item's row.
itemHeight: 22,
},
)
配置(Config)
State | Type | Description |
---|---|---|
itemHeight | number | 确保正确计算 wrapper 元素的总高度.* |
itemWidth | number | 确保正确计算 wrapper 元素的总宽度.* |
overscan | number | 预渲染的 DOM 节点数。如果滚动速度非常快,可以防止项之间出现空白 |
* itemHeight
or itemWidth
必须与渲染的每一行的高度保持同步。如果您在滚动到列表底部时看到额外的空白或抖动,请确保 itemHeight
或者 itemWidth
与行的高度相同。
* The itemHeight
or itemWidth
must be kept in sync with the height of each row rendered. If you are seeing extra whitespace or jitter when scrolling to the bottom of the list, ensure the itemHeight
or itemWidth
is the same height as the row.
Reactive list
import { useVirtualList, useToggle } from '@vueuse/core'
import { computed } from 'vue'
const [isEven, toggle] = useToggle()
const allItems = Array.from(Array(99999).keys())
const filteredList = computed(() => allItems.filter(i => isEven.value ? i % 2 === 0 : i % 2 === 1))
const { list, containerProps, wrapperProps } = useVirtualList(
filteredList,
{
itemHeight: 22,
},
)
import { useVirtualList, useToggle } from '@vueuse/core'
import { computed } from 'vue'
const [isEven, toggle] = useToggle()
const allItems = Array.from(Array(99999).keys())
const filteredList = computed(() => allItems.filter(i => isEven.value ? i % 2 === 0 : i % 2 === 1))
const { list, containerProps, wrapperProps } = useVirtualList(
filteredList,
{
itemHeight: 22,
},
)
<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>
<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>
Horizontal list
import { useVirtualList } from '@vueuse/core'
const allItems = Array.from(Array(99999).keys())
const { list, containerProps, wrapperProps } = useVirtualList(
allItems,
{
itemWidth: 200,
},
)
import { useVirtualList } from '@vueuse/core'
const allItems = Array.from(Array(99999).keys())
const { list, containerProps, wrapperProps } = useVirtualList(
allItems,
{
itemWidth: 200,
},
)
<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>
<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>
Component Usage
该函数还通过
@vueuse/components
提供了一个无渲染的组件版本。了解更多.
This function also provides a renderless component version via the
@vueuse/components
package. Learn more about the usage.
<UseVirtualList :list="list" :options="options" height="300px">
<template #="props">
<!-- you can get current item of list here -->
<div style="height: 22px">Row {{ props.data }}</div>
</template>
</UseVirtualList>
<UseVirtualList :list="list" :options="options" height="300px">
<template #="props">
<!-- you can get current item of list here -->
<div style="height: 22px">Row {{ props.data }}</div>
</template>
</UseVirtualList>
要滚动到指定元素,可以使用组件暴露的 scrollTo(index: number) => void
To scroll to a specific element, the component exposes scrollTo(index: number) => void
.
类型声明(Type Declarations)
显示类型声明
type UseVirtualListItemSize = number | ((index: number) => number)
export interface UseHorizontalVirtualListOptions
extends UseVirtualListOptionsBase {
/**
* item width, accept a pixel value or a function that returns the height
*
* @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<T[]>,
options: UseVirtualListOptions
): UseVirtualListReturn<T>
type UseVirtualListItemSize = number | ((index: number) => number)
export interface UseHorizontalVirtualListOptions
extends UseVirtualListOptionsBase {
/**
* item width, accept a pixel value or a function that returns the height
*
* @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<T[]>,
options: UseVirtualListOptions
): UseVirtualListReturn<T>