虚拟滚动列表组件ReVirtualList
组件实现基于
Vue3
+Element Plus
+Typescript
,同时引用vueUse
+lodash-es
+tailwindCss
(不影响功能,可忽略)
在
ReList
的基础上,增加虚拟列表功能,在固定高度的基础上,可以优化大数据列表展示
思路
滚动容器默认使用List列表的父节点,需要配置 height
设置List的高度用于展示滚动条。
如果滚动容器不想使用List的父节点,可以通过 scrollTarget
指定,但是 height
需要设置为 auto
,避免List内置滚动。
通过自己封装的虚拟滚动计算hook,通过监听滚动容器的滚动行为,根据当前展示视图的滚动距离计算展示内容在列表数据中的数据索引,从而获得展示视图对于数据的索引范围,以及前置内容高度,后置内容高度,最后将前置内容高度,后置内容高度以padding的方式设置,保证滚动容器的高度始终一致。
为了优化滚动交互,增加前置预加载数量和后置预加载数量,最终得到的渲染数据的数据索引。
对于卡片布局,可能存在网格布局(多列),还需要在虚拟滚动计算时,加入网格列数参数进行计算,得到最终的一个渲染数据索引范围。
难点
- 考虑网格布局时加入列数进行虚拟滚动计算
基础
通过 items
绑定全量数据,自动进行虚拟滚动计算渲染。虚拟滚动需要指定列表项固定高度,使用前可以通过实际渲染高度或UI设计稿高度定义,默认列表项会直接使用固定高度渲染,内容超出会被隐藏。
查看 /demo/list/virtual.md
卡片列表
支持网格卡片列表的虚拟滚动展示,会自动根据网格数量进行虚拟滚动计算,得到能够占满当前滚动视图的网格数量。
查看 /demo/list/virtual-card.md
ReVirtualList属性
字段 | 说明 | 类型 | 默认值 |
---|---|---|---|
items | 必填,列表项数据集 | Record<string, any>[] | - |
metas | 必填,列表项展示配置 | ReListItemMetas | - |
title | 列表标题 | string | - |
height | 列表高度,不包括页头和页脚,默认按像素值处理 | string | number | 400 |
skeleton | 是否显示骨架屏 | boolean | true |
rowHeight | 列表项高度,建议根据实际渲染指定 | number | - |
type | 列表类型 | “card” | “list” | “list” |
grid | 响应网格,仅在type="card"下有效 | number | ReGridResponsive | 1 |
gutter | 网格间距,仅在type="card"下有效 | number | [number] | [number, number] | 16 |
除了上述属性,支持ReList所有属性,默认会被ReList实例继承
同时ReVirtualList属性也继承了CustomVirtualScrollProps属性
CustomVirtualScrollProps
字段 | 说明 | 类型 | 默认值 |
---|---|---|---|
scrollTarget | 必填,滚动容器 | HTMLElement | (() => HTMLElement) | - |
pageSize | 页大小 | MaybeRef<number> | 20 |
rowHeight | 列表项高度 | number | ((index: number) => number) | - |
previewRows | 预加载数量,默认同pageSize | MaybeRef<number> | - |
多列参数,作为虚拟滚动计算参数,VirtualList会自动响应列表的网格数量,不需要手动配置 | MaybeRef<number> | 1 | |
debounce | 滚动事件时延 | number | 300 |
ReVirtualList事件
事件名 | 说明 | 格式 |
---|---|---|
update:checks | 已选中列表发生变化时触发 | (checks: Array<string | number>) => void |
check | 点击某个复选框时触发 | (checked: boolean, id: string | number, item: Record<string, any>) => void |
ReVirtualList插槽
插槽名 | 说明 |
---|---|
default | 列表项作用域插槽,带有 item、metas 两个作用域变量 |
title | List页头标题插槽 |
extra | List页头额外信息插槽 |
footer | PageList页脚插槽,在分页器之前 |
ReVirtualList Expose
字段 | 说明 | 类型 |
---|---|---|
scrollTop | 当前滚动位置离容器顶部距离 | number |
startPadding | 前置占位高度 | number |
endPadding | 后置占位高度 | number |
startIndex | 渲染数据开始索引 | number |
endIndex | 渲染数据结束索引 | Ref<number> |
scrollTo | 滚动到指定距离 | (scrollTop: number) => void |
scrollToIndex | 滚动到指定索引位置 | (index: number) => void |
源代码
Github
可以通过查看具体实现,如果遇到问题可以留言或者提出issue。
hook
虚拟滚动的实现单独抽离了一个hook,自行查看 hook/useVirtualScroll
方法,可以利用这个hook实现自己的虚拟滚动行为。目前还是基于固定高度进行计算,提供了一个rowHeight支持配置函数动态获取高度,如果您需要动态高度可以试着通过这个配置项实现