Skip to content

虚拟列表 VirtualList

用来展示很长很长很长的列表,只有看到的部分才会被实际渲染。组件在十万数量级的数据下可流畅渲染(更多也可以,但是可能被浏览器 DOM 的最大高度截断内容)。

虚拟列表采用分层次分块策略维护前缀和。这种数据结构能将计算高度的时间复杂度控制在 O(n)O(\sqrt{n}),最终在大数据量场景下实现流畅滚动。

WARNING

浏览器对单个 DOM 的最大可滚动 / 可绘制高度存在实现差异与上限,可能导致内容在极端情况下被裁剪或无法正常滚动。例如:在 Edge 版本 141.0.3537.71 中,页面可展示的像素高度在 2.7 千万像素左右,超过此范围的内容会被截断或不可见。

在使用百万级或更大数据量时,请注意总高度(itemsCount×averageItemHeightitemsCount \times averageItemHeight)是否会接近或超过浏览器的限制。

基础使用

虚拟列表默认子元素动态高度。estimatedHeight 设置初始化时元素的预估高度,通常应该比大部分子元素高度小些。

Item #0
<template>
	<px-virtual-list :list="list" style="height: 500px" :estimated-height="20"></px-virtual-list>
</template>
<script lang="ts" setup>
import { ref, h } from 'vue'

const list = ref(
	Array.from({ length: 10000 })
		.fill(0)
		.map((_, index) => ({
			render: () => h('div', { style: `height: ${20 + index / 100}px;` }, [`Item #${index}`])
		}))
)
</script>

固定高度

虚拟列表的子元素高度固定,或者可以准确获得子元素平均高度时,可以设置 fixedHeightestimatedHeight,节省性能。

Item #0
<template>
	<px-virtual-list
		:list="list"
		style="height: 500px"
		fixed-height
		:estimated-height="20"
	></px-virtual-list>
</template>
<script lang="ts" setup>
import { ref, h } from 'vue'

const list = ref(
	Array.from({ length: 10000 })
		.fill(0)
		.map((_, index) => ({
			render: () => h('div', { style: `height: 20px;` }, [`Item #${index}`])
		}))
)
</script>

滚动容器

使用 'scroll-container' 插槽可自定义滚动容器。

Item #0
<script lang="ts">
import { ref, h, defineComponent } from 'vue'
import { VirtualList, ScrollBar } from '@pixelium/web-vue'
import type { JSX } from 'vue/jsx-runtime'

export default defineComponent({
	setup() {
		const list = ref(
			Array.from({ length: 10000 })
				.fill(0)
				.map((_, index) => ({
					render: () =>
						h('div', { style: `height: ${20 + index / 100}px;` }, [`Item #${index}`])
				}))
		)
		return () =>
			h(
				VirtualList,
				{
					list: list.value,
					estimatedHeight: 20,
					style: 'height: 500px'
				},
				{
					'scroll-container': ({
						children,
						onScroll
					}: {
						children: JSX.Element
						onScroll: (event: Event) => void
					}) =>
						h(
							ScrollBar,
							{ style: 'height: 500px', onScroll: onScroll },
							{
								default: () => children
							}
						)
				}
			)
	}
})
</script>

API

VirtualListProps

属性类型可选默认值描述版本
list{ render: ValidContent; key?: string | number | symbol }[]用于渲染的数据数组。0.0.3
fixedHeightbooleanfalse是否为定高模式。0.0.3
estimatedHeightnumber28预估项高(用于初始化和测量前的估算),单位 px。0.0.3
buffernumber10缓冲项数,控制视窗前后多渲染的项数以避免快速滚动时闪烁。0.0.3

VirtualListSlots

插槽参数描述版本
scroll-containerchildren: JSX.Element, onScroll: (event: Event) => void0.1.0