diff --git a/packages/varlet-ui/src/virtual-list/VirtualList.vue b/packages/varlet-ui/src/virtual-list/VirtualList.vue new file mode 100644 index 00000000000..4fa84e1f5ba --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/VirtualList.vue @@ -0,0 +1,263 @@ + + + + + diff --git a/packages/varlet-ui/src/virtual-list/__tests__/index.spec.js b/packages/varlet-ui/src/virtual-list/__tests__/index.spec.js new file mode 100644 index 00000000000..23ed45508e2 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/__tests__/index.spec.js @@ -0,0 +1,8 @@ +import { createApp } from 'vue' +import { expect, test } from 'vitest' +import VirtualList from '..' + +test('virtual-list plugin', () => { + const app = createApp({}).use(VirtualList) + expect(app.component(VirtualList.name)).toBeTruthy() +}) diff --git a/packages/varlet-ui/src/virtual-list/docs/en-US.md b/packages/varlet-ui/src/virtual-list/docs/en-US.md new file mode 100644 index 00000000000..4328281d9f4 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/docs/en-US.md @@ -0,0 +1,192 @@ +# VirtualList + +### Intro + +A high-performance scrolling list for displaying large amounts of data, using virtual scrolling technology to render only elements in the visible area, greatly improving the performance of long lists. + +Virtual lists should only be used when dealing with large amounts of data (typically hundreds to thousands of items) to improve rendering performance. For most common scenarios, regular list rendering is sufficient. + +This component supports automatic handling of variable height list items. It measures and updates the actual height of each list item after rendering, ensuring accurate scroll positioning. + +### Basic Usage + +Set list data with the `data` property, set the list item height with `item-height`, and customize the list item content with the default slot. + +```html + + + + + +``` + +### Variable Height Items + +The component automatically measures and adapts to list items with different heights. In this case, `item-height` is used as an estimated height. + +```html + + + + + +``` + +### Set Container Height + +Set the container height with the `container-height` property or CSS styles. + +```html + + + +``` + +### Scroll to Specified Position + +Scroll to a specified position using the `scrollTo` method. + +```html +Scroll to Item 50 + + + + + +``` + +## API + +### Props + +| Prop | Description | Type | Default | +| --- | --- | --- | --- | +| `data` | List data | _any[]_ | `[]` | +| `item-height` | List item height (unit: pixel), used as estimated height for variable height lists | _number \| string_ | `50` | +| `buffer-size` | Buffer size (number of pre-rendered list items above and below) | _number_ | `5` | +| `container-height` | Container height (unit: pixel) | _number \| string_ | `-` | + +### Methods + +| Method | Description | Parameters | Return | +| --- | --- | --- | --- | +| `scrollTo` | Scroll to the specified index position | `index: number` | `-` | + +### Events + +| Event | Description | Arguments | +| --- | --- | --- | +| `scroll` | Triggered when the list scrolls | `event: Event` | + +### Slots + +| Name | Description | SlotProps | +| --- | --- | --- | +| `default` | List item content | `{ item: any, index: number }` | + +### Style Variables + +Here are the CSS variables used by the component, which can be customized using [StyleProvider](#/en-US/style-provider). + +| Variable | Default | +| --- | --- | +| `--virtual-list-height` | `100%` | + diff --git a/packages/varlet-ui/src/virtual-list/docs/zh-CN.md b/packages/varlet-ui/src/virtual-list/docs/zh-CN.md new file mode 100644 index 00000000000..3f8ec5873b6 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/docs/zh-CN.md @@ -0,0 +1,192 @@ +# 虚拟滚动列表 + +### 介绍 + +用于展示大量数据的高性能滚动列表,通过虚拟滚动技术只渲染可视区域内的元素,极大提高了长列表的性能。 + +只有在处理大量数据(通常是几百到几千条)需要提高渲染性能时,才需要使用虚拟列表。对于大多数常见场景,普通的列表渲染就足够了。 + +本组件支持自动处理不定高列表项,会在渲染后自动测量并更新每个列表项的实际高度,确保滚动位置的准确性。 + +### 基本使用 + +通过 `data` 属性设置列表数据,通过 `item-height` 设置列表项高度,通过默认插槽自定义列表项内容。 + +```html + + + + + +``` + +### 不定高列表项 + +组件会自动测量并适应不同高度的列表项,`item-height` 在这种情况下作为预估高度使用。 + +```html + + + + + +``` + +### 设置容器高度 + +通过 `container-height` 属性或 CSS 样式设置容器高度。 + +```html + + + +``` + +### 滚动到指定位置 + +通过 `scrollTo` 方法滚动到指定位置。 + +```html +滚动到第50项 + + + + + +``` + +## API + +### 属性 + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| `data` | 列表数据 | _any[]_ | `[]` | +| `item-height` | 列表项高度(单位:像素),对于不定高列表作为预估高度使用 | _number \| string_ | `50` | +| `buffer-size` | 缓冲区大小(上下预渲染的列表项数量) | _number_ | `5` | +| `container-height` | 容器高度(单位:像素) | _number \| string_ | `-` | + +### 方法 + +| 方法名 | 说明 | 参数 | 返回值 | +| --- | --- | --- | --- | +| `scrollTo` | 滚动到指定索引位置 | `index: number` | `-` | + +### 事件 + +| 事件名 | 说明 | 参数 | +| --- | --- | --- | +| `scroll` | 列表滚动时触发 | `event: Event` | + +### 插槽 + +| 插槽名 | 说明 | 参数 | +| --- | --- | --- | +| `default` | 列表项内容 | `{ item: any, index: number }` | + +### 样式变量 + +以下为组件使用的 css 变量,可以使用 [StyleProvider 组件](#/zh-CN/style-provider) 进行样式定制。 + +| 变量名 | 默认值 | +| --- | --- | +| `--virtual-list-height` | `100%` | + diff --git a/packages/varlet-ui/src/virtual-list/example/index.vue b/packages/varlet-ui/src/virtual-list/example/index.vue new file mode 100644 index 00000000000..fbf6a870dc9 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/example/index.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/packages/varlet-ui/src/virtual-list/example/locale/en-US.ts b/packages/varlet-ui/src/virtual-list/example/locale/en-US.ts new file mode 100644 index 00000000000..adb3ea5e522 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/example/locale/en-US.ts @@ -0,0 +1,7 @@ +export default { + // Example locale + basicUsage: 'Basic Usage', + listItem: 'List Item', + variableHeight: 'Variable Height Items', + variableDesc: 'This is a variable height list item. The component handles scroll position automatically.', +} diff --git a/packages/varlet-ui/src/virtual-list/example/locale/index.ts b/packages/varlet-ui/src/virtual-list/example/locale/index.ts new file mode 100644 index 00000000000..e031be8c1a4 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/example/locale/index.ts @@ -0,0 +1,17 @@ +import { Locale } from '@varlet/ui' +import enUS from './en-US' +import zhCN from './zh-CN' + +const { add, use: exampleUse, t, merge } = Locale.useLocale() + +const use = (lang: string) => { + Locale.use(lang) + exampleUse(lang) +} + +Locale.add('zh-CN', Locale.zhCN) +Locale.add('en-US', Locale.enUS) +add('zh-CN', zhCN) +add('en-US', enUS) + +export { add, t, merge, use } diff --git a/packages/varlet-ui/src/virtual-list/example/locale/zh-CN.ts b/packages/varlet-ui/src/virtual-list/example/locale/zh-CN.ts new file mode 100644 index 00000000000..cbb8d697a1c --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/example/locale/zh-CN.ts @@ -0,0 +1,6 @@ +export default { + basicUsage: '基本使用', + listItem: '列表项', + variableHeight: '不定高列表项', + variableDesc: '这是一个高度不固定的列表项,组件会自动处理滚动位置', +} diff --git a/packages/varlet-ui/src/virtual-list/index.ts b/packages/varlet-ui/src/virtual-list/index.ts new file mode 100644 index 00000000000..f616f554767 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/index.ts @@ -0,0 +1,12 @@ +import { withInstall, withPropsDefaultsSetter } from '../utils/components' +import { props as virtualListProps } from './props' +import VirtualList from './VirtualList.vue' + +withInstall(VirtualList) +withPropsDefaultsSetter(VirtualList, virtualListProps) + +export { virtualListProps } + +export const _VirtualListComponent = VirtualList + +export default VirtualList diff --git a/packages/varlet-ui/src/virtual-list/props.ts b/packages/varlet-ui/src/virtual-list/props.ts new file mode 100644 index 00000000000..35f6dbd4c3c --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/props.ts @@ -0,0 +1,21 @@ +import { defineListenerProp } from '../utils/components' + +export const props = { + data: { + type: Array, + default: () => [], + }, + itemHeight: { + type: [Number, String], + default: 50, + }, + bufferSize: { + type: Number, + default: 5, + }, + containerHeight: { + type: [Number, String], + default: null, + }, + onScroll: defineListenerProp<(e: Event) => void>(), +} diff --git a/packages/varlet-ui/src/virtual-list/virtualList.d.ts b/packages/varlet-ui/src/virtual-list/virtualList.d.ts new file mode 100644 index 00000000000..d4a661155ea --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/virtualList.d.ts @@ -0,0 +1,35 @@ +import { VarComponent } from '../varComponent' + +export interface VirtualListProps { + /** 列表数据 */ + data?: any[] + /** 列表项高度(单位:像素) */ + itemHeight?: number | string + /** 缓冲区大小(上下预渲染的列表项数量) */ + bufferSize?: number + /** 容器高度(单位:像素) */ + containerHeight?: number | string + /** 滚动事件回调 */ + onScroll?: (e: Event) => void +} + +export interface VirtualListSlots { + /** 默认插槽,用于自定义列表项内容 */ + default: (item: { item: any; index: number }) => JSX.Element +} + +export interface VirtualListMethods { + /** 滚动到指定索引位置 */ + scrollTo: (index: number) => void +} + +export type VirtualListListeners = { + /** 滚动事件监听器 */ + onScroll?: (e: Event) => void +} + +export type VirtualList = VarComponent + +export class _VirtualListComponent extends VarComponent { + scrollTo(index: number): void +} diff --git a/packages/varlet-ui/src/virtual-list/virtualList.less b/packages/varlet-ui/src/virtual-list/virtualList.less new file mode 100644 index 00000000000..8024ffaa3d4 --- /dev/null +++ b/packages/varlet-ui/src/virtual-list/virtualList.less @@ -0,0 +1,34 @@ +:root { + --virtual-list-height: 100%; +} + +.var-virtual-list { + /* 基础样式 */ + height: var(--virtual-list-height); + overflow-y: auto; + position: relative; + + /* 幽灵层 - 撑开滚动区域 */ + &__phantom { + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: -1; + } + + /* 内容层 - 实际渲染的可视区域 */ + &__content { + position: absolute; + top: 0; + left: 0; + right: 0; + width: 100%; + } + + /* 列表项容器 */ + &__item { + width: 100%; + box-sizing: border-box; + } +} diff --git a/packages/varlet-ui/types/styleVars.d.ts b/packages/varlet-ui/types/styleVars.d.ts index 4d13dbad5b9..8503050ee4e 100644 --- a/packages/varlet-ui/types/styleVars.d.ts +++ b/packages/varlet-ui/types/styleVars.d.ts @@ -900,6 +900,7 @@ interface BaseStyleVars { '--uploader-disabled-color'?: string '--uploader-disabled-text-color'?: string '--uploader-loading-background'?: string + '--virtual-list-height'?: string '--watermark-content-color'?: string [key: PropertyKey]: string } diff --git a/packages/varlet-ui/varlet.config.mjs b/packages/varlet-ui/varlet.config.mjs index 681e8a61c49..01445230a26 100644 --- a/packages/varlet-ui/varlet.config.mjs +++ b/packages/varlet-ui/varlet.config.mjs @@ -328,6 +328,14 @@ export default defineConfig({ doc: 'list', type: 2, }, + { + text: { + 'zh-CN': 'VirtualList 虚拟滚动列表', + 'en-US': 'VirtualList', + }, + doc: 'virtual-list', + type: 2, + }, { text: { 'zh-CN': 'Swipe 轮播',