npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

virtual-list-common

v0.4.4

Published

vue3,react 通用虚拟列表,用于高效渲染大量数据的列表,仅渲染可见区域的元素并复用 DOM。A Vue and React universal virtual list for efficiently rendering large lists with large data, only rendering elements in the visible area and reusing DOM.

Readme

virtual-list-common 虚拟列表

该项目是一个 Vue、React 通用虚拟列表,用于高效渲染大量数据的列表,仅渲染可见区域的元素并复用 DOM。 适用于 Vue 和 React 项目,提供完整的 TypeScript 类型支持。 由于使用了 IntersectionObserver API,所以需要浏览器支持。

安装

npm install virtual-list-common
# 或
pnpm add virtual-list-common
# 或
yarn add virtual-list-common

快速开始

方式一:使用框架原生组件(推荐)

从 v0.1.0 开始,提供了 Vue3 和 React 的原生组件支持,使用更加便捷。

Vue 3 组件

<template>
  <VirtualList
    :items="items"
    :itemHeight="310"
    :itemWidth="200"
    :columns="2"
    height="600px"
    @itemClick="handleItemClick"
    @scroll="handleScroll"
    ref="virtualListRef"
    :renderItem="renderItem"
  >
  </VirtualList>
</template>

<script setup>
import { ref } from 'vue';
import { VirtualListVue as VirtualList } from 'virtual-list-common/vue';

const items = ref([
  'https://picsum.photos/200/300?random=1',
  'https://picsum.photos/200/300?random=2',
  // ...
]);

const virtualListRef = ref(null);

// 自定义渲染函数
const renderItem = (index, itemData) => {
  const div = document.createElement('div');
  div.className = 'custom-item';
  div.innerHTML = `<img src="${itemData}" alt="Item ${index}" /><span>Item ${index}</span>`;
  return div;
};

const handleItemClick = ({ index, itemData }) => {
  console.log('Clicked item:', index, itemData);
};

const handleScroll = ({ scrollTop, firstVisibleIndex, lastVisibleIndex }) => {
  console.log('Scroll position:', scrollTop);
};

// 使用暴露的方法
const scrollToItem = (index) => {
  virtualListRef.value?.scrollToIndex(index, { immediate: false });
};
</script>

React 组件

import { useRef, useState } from 'react';
import { VirtualListReact as VirtualList } from 'virtual-list-common/react';

function App() {
  const [items] = useState([
    'https://picsum.photos/200/300?random=1',
    'https://picsum.photos/200/300?random=2',
    // ...
  ]);
  
  const virtualListRef = useRef(null);

  // 自定义渲染函数
  const renderItem = (index, itemData) => (
    <div className="custom-item">
      <img src={itemData} alt={`Item ${index}`} />
      <span>Item {index}</span>
    </div>
  );

  const handleItemClick = (index, itemData) => {
    console.log('Clicked item:', index, itemData);
  };

  const handleScroll = ({ scrollTop, firstVisibleIndex, lastVisibleIndex }) => {
    console.log('Scroll position:', scrollTop);
  };

  // 使用暴露的方法
  const scrollToItem = (index) => {
    virtualListRef.current?.scrollToIndex(index, { immediate: false });
  };

  return (
    <VirtualList
      ref={virtualListRef}
      items={items}
      itemHeight={310}
      itemWidth={200}
      columns={2}
      height="600px"
      renderItem={renderItem}
      onItemClick={handleItemClick}
      onScroll={handleScroll}
    />
  );
}

方式二:使用核心类(高级用法)

如果你需要更底层的控制,可以直接使用 VirtualList 核心类。

核心类基础用法

import VirtualList from 'virtual-list-common';

const container = document.getElementById('container');
const items = [
  'https://picsum.photos/200/300?random=1',
  'https://picsum.photos/200/300?random=2',
  // ...
];

const virtualList = new VirtualList(container, items, {
    itemHeight: 310,
    itemWidth: 200,
    columns: 2
});

自定义渲染(使用核心类)

// Vue 中使用核心类
import { createApp, h } from 'vue';
import VirtualList from 'virtual-list-common';
import MyVueComponent from './MyVueComponent.vue';

const virtualList = new VirtualList(container, items, {
    onRenderItem: (index, itemData) => {
        const wrapper = document.createElement('div');
        const app = createApp({
            render: () => h(MyVueComponent, { data: itemData, index })
        });
        app.mount(wrapper);
        return wrapper;
    }
});

// React 中使用核心类
import { createRoot } from 'react-dom/client';
import VirtualList from 'virtual-list-common';
import MyReactComponent from './MyReactComponent';

const virtualList = new VirtualList(container, items, {
    onRenderItem: (index, itemData) => {
        const wrapper = document.createElement('div');
        const root = createRoot(wrapper);
        root.render(<MyReactComponent data={itemData} index={index} />);
        return wrapper;
    }
});

组件/类 API 参考

VirtualListVue 组件属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | items | Array | 必填 | 列表数据数组 | | itemHeight | number | 310 | 每个项目的高度(像素) | | itemWidth | number | 200 | 每个项目的宽度(像素) | | columns | number | 2 | 列数 | | gap | number | 5 | 项目间距(像素) | | buffer | number | 2 | 缓冲区大小(行数) | | height | string/number | '100%' | 容器高度 | | className | string | '' | 容器 CSS 类名 | | style | Object | {} | 容器内联样式 | | preloadCount | number | 24 | 初始预加载数量 | | scrollDamping | number | 0.09 | 滚动阻尼系数 | | renderItem | Function | null | 自定义渲染函数 (index, itemData) => HTMLElement,返回 DOM 元素 | | onItemClick | Function | null | 点击事件回调 (index, itemData, element) => void | | onScroll | Function | null | 滚动事件回调 (scrollTop, firstVisibleIndex, lastVisibleIndex) => void | | enableInfiniteScroll | boolean | false | 是否启用无限滚动功能 | | onLoadMore | Function | null | 加载更多数据的回调函数,返回 false 或空数组表示没有更多数据 | | loadingIndicator | HTMLElement/string | null | 自定义加载指示器元素或 HTML 字符串 | | endReachedMessage | string | '没有更多数据' | 没有更多数据时显示的提示信息 | | infiniteScrollThreshold | number | 200 | 触发加载更多的距离阈值(像素) | | hasMoreData | boolean | true | 是否还有更多数据可加载 | | orientation | string | 'vertical' | 滚动方向,可选值:'vertical'(垂直)或 'horizontal'(横向) | | maxRows | number | Infinity | 横向滚动模式下的最大行数,默认值为 1(当设置为 Infinity 时) | | itemSpacing | number | 0 | 横向滚动模式下项目之间的间距(像素) | | enableAutoHeight | boolean | false | 是否启用自适应高度(仅垂直模式有效) | | estimatedItemHeight | number | 200 | 自适应高度模式下的预估项目高度(像素) |

VirtualListVue 事件

| 事件名 | 参数 | 说明 | |--------|------|------| | itemClick | { index, itemData, element } | 项目点击时触发 | | scroll | { scrollTop, firstVisibleIndex, lastVisibleIndex } | 滚动时触发 | | update | VirtualList 实例 | 实例更新时触发 | | loadMore | - | 无限滚动触发加载更多时触发(启用 enableInfiniteScroll 时) |

VirtualListVue 方法(通过 ref 调用)

| 方法名 | 参数 | 说明 | |--------|------|------| | scrollToIndex(index, options) | index: 目标索引, options: { immediate?, duration?, easing? } | 滚动到指定索引 | | scrollToBottom(options) | options: { immediate?, duration?, easing? } | 滚动到末尾(垂直模式为底部,横向模式为右侧) | | scrollToTop(options) | options: { immediate?, duration?, easing? } | 滚动到开始位置(垂直模式为顶部,横向模式为左侧) | | scrollToEnd(options) | options: { immediate?, duration?, easing? } | scrollToBottom 的别名,用于横向模式语义更清晰 | | scrollToStart(options) | options: { immediate?, duration?, easing? } | scrollToTop 的别名,用于横向模式语义更清晰 | | scrollTo(scrollTop, options) | scrollTop: 目标位置, options: { immediate?, duration?, easing? } | 滚动到指定位置 | | getFirstVisibleIndex() | - | 获取第一个可见项目索引 | | getLastVisibleIndex() | - | 获取最后一个可见项目索引 | | updateItems(newItems) | newItems: 新数据数组 | 更新数据源 | | destroy() | - | 销毁实例,清理资源 | | setHasMoreData(value) | value: boolean | 设置是否还有更多数据可加载 |

VirtualListReact 组件属性

与 Vue 组件属性相同,事件通过 onItemClickonScroll 回调处理。

VirtualListReact 方法(通过 ref 调用)

与 Vue 组件方法相同。

VirtualList 核心类配置

const options = {
    itemHeight: 310,        // 项目高度
    itemWidth: 200,         // 项目宽度
    columns: 2,             // 列数
    gap: 5,                 // 间距
    buffer: 2,              // 缓冲区行数
    preloadCount: 24,       // 预加载数量
    maxPoolSize: 50,        // DOM 元素池最大大小
    scrollDamping: 0.09,    // 滚动阻尼
    preloadDistance: 800,   // 预加载距离
    onRenderItem: null,     // 自定义渲染函数
    onScroll: null,         // 滚动回调
    onItemClick: null,      // 点击回调
    
    // 无限滚动配置
    enableInfiniteScroll: false,    // 是否启用无限滚动
    onLoadMore: null,               // 加载更多回调
    loadingIndicator: null,         // 自定义加载指示器
    endReachedMessage: '没有更多数据', // 结束提示信息
    infiniteScrollThreshold: 200,   // 触发加载阈值
    hasMoreData: true,              // 是否还有更多数据

    // 横向滚动配置
    orientation: 'vertical',        // 滚动方向:'vertical' 或 'horizontal'
    maxRows: Infinity,              // 横向模式下最大行数(Infinity 时默认为 1 行)
    itemSpacing: 0,                 // 横向模式下项目间距

    // 自适应高度配置(仅垂直模式有效)
    enableAutoHeight: false,        // 是否启用自适应高度
    estimatedItemHeight: 200        // 预估项目高度(用于初始渲染)
};

在 Vue 中使用核心类示例

<template>
  <div ref="container"></div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import VirtualList from 'virtual-list-common';

const container = ref(null);
let virtualList = null;

onMounted(() => {
    const items = ['url1', 'url2', /* ... */];
    virtualList = new VirtualList(container.value, items, {
        itemHeight: 310,
        columns: 2
    });
});

onBeforeUnmount(() => {
    virtualList?.destroy();
});
</script>

在 React 中使用核心类示例

import { useEffect, useRef } from 'react';
import VirtualList from 'virtual-list-common';

function App() {
    const containerRef = useRef(null);
    
    useEffect(() => {
        const items = ['url1', 'url2', /* ... */];
        const virtualList = new VirtualList(containerRef.current, items, {
            itemHeight: 310,
            columns: 2
        });
        
        return () => {
            virtualList.destroy();
        };
    }, []);
    
    return <div ref={containerRef} />;
}

无限滚动功能

从 v0.2.0 开始,支持无限滚动功能,可以在用户滚动到列表底部时自动加载更多数据。

Vue 3 无限滚动示例

<template>
  <VirtualList
    :items="items"
    :itemHeight="310"
    :itemWidth="200"
    :columns="2"
    height="600px"
    :enableInfiniteScroll="true"
    :hasMoreData="hasMore"
    :onLoadMore="loadMore"
    endReachedMessage="已经到底啦~"
    @loadMore="handleLoadMore"
    ref="virtualListRef"
  />
</template>

<script setup>
import { ref } from 'vue';
import { VirtualListVue as VirtualList } from 'virtual-list-common/vue';

const items = ref([]);
const hasMore = ref(true);
const page = ref(1);

// 加载更多数据
const loadMore = async () => {
  const newItems = await fetchData(page.value);
  if (newItems.length === 0) {
    hasMore.value = false;
    return false; // 返回 false 表示没有更多数据
  }
  items.value = [...items.value, ...newItems];
  page.value++;
  return true;
};

const handleLoadMore = () => {
  console.log('触发加载更多');
};
</script>

React 无限滚动示例

import { useRef, useState, useCallback } from 'react';
import { VirtualListReact as VirtualList } from 'virtual-list-common/react';

function App() {
  const [items, setItems] = useState([]);
  const [hasMore, setHasMore] = useState(true);
  const pageRef = useRef(1);
  const virtualListRef = useRef(null);

  // 加载更多数据
  const loadMore = useCallback(async () => {
    const newItems = await fetchData(pageRef.current);
    if (newItems.length === 0) {
      setHasMore(false);
      return false; // 返回 false 表示没有更多数据
    }
    setItems(prev => [...prev, ...newItems]);
    pageRef.current++;
    return true;
  }, []);

  return (
    <VirtualList
      ref={virtualListRef}
      items={items}
      itemHeight={310}
      itemWidth={200}
      columns={2}
      height="600px"
      enableInfiniteScroll={true}
      hasMoreData={hasMore}
      onLoadMore={loadMore}
      endReachedMessage="已经到底啦~"
    />
  );
}

核心类无限滚动示例

import VirtualList from 'virtual-list-common';

let page = 1;
let hasMore = true;

const virtualList = new VirtualList(container, [], {
    itemHeight: 310,
    itemWidth: 200,
    columns: 2,
    enableInfiniteScroll: true,
    hasMoreData: true,
    infiniteScrollThreshold: 300, // 距离底部 300px 时触发加载
    endReachedMessage: '已经到底啦~',
    onLoadMore: async () => {
        if (!hasMore) return false;
        
        const newItems = await fetchData(page);
        if (newItems.length === 0) {
            hasMore = false;
            virtualList.setHasMoreData(false);
            return false;
        }
        
        // 更新数据
        virtualList.updateItems([...virtualList.items, ...newItems]);
        page++;
        return true;
    }
});

横向滚动功能

从 v0.3.0 开始,支持横向滚动模式,通过设置 orientation: 'horizontal' 开启。

Vue 3 横向滚动示例

<template>
  <VirtualList
    :items="items"
    :itemHeight="200"
    :itemWidth="300"
    :columns="3"
    height="400px"
    orientation="horizontal"
    :maxRows="2"
    :itemSpacing="10"
    @itemClick="handleItemClick"
    ref="virtualListRef"
  />
</template>

<script setup>
import { ref } from 'vue';
import { VirtualListVue as VirtualList } from 'virtual-list-common/vue';

const items = ref([
  'https://picsum.photos/300/200?random=1',
  'https://picsum.photos/300/200?random=2',
  // ...
]);

const virtualListRef = ref(null);

const handleItemClick = ({ index, itemData }) => {
  console.log('Clicked item:', index, itemData);
};

// 横向模式下使用语义化方法
const scrollToStart = () => {
  virtualListRef.value?.scrollToStart({ immediate: false });
};

const scrollToEnd = () => {
  virtualListRef.value?.scrollToEnd({ immediate: false });
};
</script>

React 横向滚动示例

import { useRef, useState } from 'react';
import { VirtualListReact as VirtualList } from 'virtual-list-common/react';

function App() {
  const [items] = useState([
    'https://picsum.photos/300/200?random=1',
    'https://picsum.photos/300/200?random=2',
    // ...
  ]);
  
  const virtualListRef = useRef(null);

  const handleItemClick = (index, itemData) => {
    console.log('Clicked item:', index, itemData);
  };

  // 横向模式下使用语义化方法
  const scrollToStart = () => {
    virtualListRef.current?.scrollToStart({ immediate: false });
  };

  const scrollToEnd = () => {
    virtualListRef.current?.scrollToEnd({ immediate: false });
  };

  return (
    <VirtualList
      ref={virtualListRef}
      items={items}
      itemHeight={200}
      itemWidth={300}
      columns={3}
      height="400px"
      orientation="horizontal"
      maxRows={2}
      itemSpacing={10}
      onItemClick={handleItemClick}
    />
  );
}

核心类横向滚动示例

import VirtualList from 'virtual-list-common';

const virtualList = new VirtualList(container, items, {
    itemHeight: 200,
    itemWidth: 300,
    columns: 3,
    orientation: 'horizontal',
    maxRows: 2,          // 限制为 2 行
    itemSpacing: 10      // 项目间距 10px
});

// 使用语义化方法
virtualList.scrollToStart();  // 滚动到左侧
virtualList.scrollToEnd();    // 滚动到右侧

横向滚动配置说明

| 配置项 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | orientation | string | 'vertical' | 滚动方向,设置为 'horizontal' 启用横向滚动 | | maxRows | number | Infinity | 横向模式下的最大行数,默认值为 1(当设置为 Infinity 时) | | itemSpacing | number | 0 | 横向模式下项目之间的水平间距(像素) |

注意事项

  • 横向模式下,默认显示 1 行(当 maxRows 未设置或为 Infinity 时)
  • 横向模式下会自动配置 Lenis 为水平滚动
  • 无限滚动功能在横向模式下也可正常使用,会在右侧触发加载
  • scrollToTop()/scrollToBottom() 在横向模式下分别滚动到左侧/右侧
  • 建议使用 scrollToStart()/scrollToEnd() 方法,语义更清晰

自适应高度功能

从 v0.4.0 开始,支持自适应高度模式,允许列表项目具有不同的高度。该功能仅在垂直滚动模式下有效。

Vue 3 自适应高度示例

<template>
  <VirtualList
    :items="items"
    :itemWidth="200"
    :columns="2"
    height="600px"
    :enableAutoHeight="true"
    :estimatedItemHeight="200"
    :renderItem="renderItem"
    @itemClick="handleItemClick"
    ref="virtualListRef"
  />
</template>

<script setup>
import { ref } from 'vue';
import { VirtualListVue as VirtualList } from 'virtual-list-common/vue';

const items = ref([
  { title: '短内容', content: '这是一段简短的内容' },
  { title: '长内容', content: '这是一段较长的内容,可能包含多行文字...' },
  // ...
]);

const virtualListRef = ref(null);

// 自定义渲染函数 - 高度由内容决定
const renderItem = (index, itemData) => {
  const div = document.createElement('div');
  div.className = 'auto-height-item';
  div.innerHTML = `
    <h3>${itemData.title}</h3>
    <p>${itemData.content}</p>
  `;
  return div;
};

const handleItemClick = ({ index, itemData }) => {
  console.log('Clicked item:', index, itemData);
};
</script>

<style>
.auto-height-item {
  padding: 16px;
  background: #f5f5f5;
  border-radius: 8px;
}
</style>

React 自适应高度示例

import { useRef, useState } from 'react';
import { VirtualListReact as VirtualList } from 'virtual-list-common/react';

function App() {
  const [items] = useState([
    { title: '短内容', content: '这是一段简短的内容' },
    { title: '长内容', content: '这是一段较长的内容,可能包含多行文字...' },
    // ...
  ]);
  
  const virtualListRef = useRef(null);

  // 自定义渲染函数 - 高度由内容决定
  const renderItem = (index, itemData) => (
    <div className="auto-height-item">
      <h3>{itemData.title}</h3>
      <p>{itemData.content}</p>
    </div>
  );

  const handleItemClick = (index, itemData) => {
    console.log('Clicked item:', index, itemData);
  };

  return (
    <VirtualList
      ref={virtualListRef}
      items={items}
      itemWidth={200}
      columns={2}
      height="600px"
      enableAutoHeight={true}
      estimatedItemHeight={200}
      renderItem={renderItem}
      onItemClick={handleItemClick}
    />
  );
}

核心类自适应高度示例

import VirtualList from 'virtual-list-common';

const virtualList = new VirtualList(container, items, {
    itemWidth: 200,
    columns: 2,
    enableAutoHeight: true,
    estimatedItemHeight: 200,
    onRenderItem: (index, itemData) => {
        const div = document.createElement('div');
        div.className = 'auto-height-item';
        div.innerHTML = `
            <h3>${itemData.title}</h3>
            <p>${itemData.content}</p>
        `;
        return div;
    }
});

自适应高度配置说明

| 配置项 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | enableAutoHeight | boolean | false | 是否启用自适应高度(仅垂直模式有效) | | estimatedItemHeight | number | 200 | 预估项目高度(像素),用于初始渲染和滚动位置计算 |

注意事项

  • 自适应高度仅在垂直滚动模式下生效,横向模式下会自动忽略此配置
  • 启用自适应高度时,itemHeight 配置将被忽略
  • 为获得最佳性能,建议设置一个接近实际平均高度的 estimatedItemHeight
  • 自适应高度模式与无限滚动功能兼容
  • 每行的高度取该行中所有列的最大高度

TypeScript 支持

从 v0.4.0 开始,提供完整的 TypeScript 类型支持,包括自动生成的类型声明文件。

导出的类型

import VirtualList, {
  Orientation,
  EasingFunction,
  ScrollOptions,
  VirtualListOptions
} from 'virtual-list-common';

import {
  VirtualListVue,
  VirtualListVueProps,
  VirtualListVueExpose
} from 'virtual-list-common/vue';

import {
  VirtualListReact,
  VirtualListReactProps,
  VirtualListReactRef
} from 'virtual-list-common/react';

Vue 3 + TypeScript 示例

<template>
  <VirtualList
    :items="items"
    :itemHeight="310"
    :itemWidth="200"
    :columns="2"
    height="600px"
    @itemClick="handleItemClick"
    ref="virtualListRef"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { VirtualListVue as VirtualList, VirtualListVueExpose } from 'virtual-list-common/vue';
import type { ScrollOptions } from 'virtual-list-common';

const items = ref<string[]>([
  'https://picsum.photos/200/300?random=1',
  'https://picsum.photos/200/300?random=2',
]);

const virtualListRef = ref<InstanceType<typeof VirtualList> | null>(null);

const handleItemClick = ({ index, itemData }: { index: number; itemData: string }) => {
  console.log('Clicked item:', index, itemData);
};

const scrollToItem = (index: number, options?: ScrollOptions) => {
  virtualListRef.value?.scrollToIndex(index, options);
};
</script>

React + TypeScript 示例

import { useRef, useState } from 'react';
import { VirtualListReact as VirtualList, VirtualListReactRef } from 'virtual-list-common/react';
import type { ScrollOptions } from 'virtual-list-common';

function App() {
  const [items] = useState<string[]>([
    'https://picsum.photos/200/300?random=1',
    'https://picsum.photos/200/300?random=2',
  ]);
  
  const virtualListRef = useRef<VirtualListReactRef>(null);

  const handleItemClick = (index: number, itemData: string) => {
    console.log('Clicked item:', index, itemData);
  };

  const scrollToItem = (index: number, options?: ScrollOptions) => {
    virtualListRef.current?.scrollToIndex(index, options);
  };

  return (
    <VirtualList
      ref={virtualListRef}
      items={items}
      itemHeight={310}
      itemWidth={200}
      columns={2}
      height="600px"
      onItemClick={handleItemClick}
    />
  );
}

核心类 + TypeScript 示例

import VirtualList, { VirtualListOptions, ScrollOptions } from 'virtual-list-common';

const container = document.getElementById('container') as HTMLElement;
const items: string[] = [
  'https://picsum.photos/200/300?random=1',
  'https://picsum.photos/200/300?random=2',
];

const options: VirtualListOptions = {
  itemHeight: 310,
  itemWidth: 200,
  columns: 2,
  onItemClick: (index: number, itemData: string, element: HTMLElement) => {
    console.log('Clicked:', index, itemData);
  }
};

const virtualList = new VirtualList(container, items, options);

// 使用类型化的滚动选项
const scrollOptions: ScrollOptions = {
  immediate: false,
  duration: 500
};

virtualList.scrollToIndex(10, scrollOptions);

类型定义说明

| 类型 | 说明 | |------|------| | Orientation | 滚动方向:'vertical' \| 'horizontal' | | EasingFunction | 缓动函数:(t: number) => number | | ScrollOptions | 滚动选项:{ immediate?, duration?, easing? } | | VirtualListOptions | 虚拟列表配置选项接口 | | VirtualListVueProps | Vue 组件 Props 类型 | | VirtualListVueExpose | Vue 组件暴露方法类型 | | VirtualListReactProps | React 组件 Props 类型 | | VirtualListReactRef | React 组件 Ref 类型 |


注意事项

  1. 生命周期管理:在 Vue/React 组件销毁时,虚拟列表会自动清理资源。但如果直接使用核心类,需要手动调用 virtualList.destroy()

  2. 响应式数据

    • 使用 Vue 组件时,items 是响应式的,数据变化会自动更新列表。
    • 使用 React 组件时,items 变化会自动触发更新。
    • 使用核心类时,如果 items 变化,需要调用 virtualList.updateItems(newItems)
  3. 自定义渲染

    • Vue 组件支持使用 renderItem 属性自定义渲染,接收 (index, itemData) 参数并返回 DOM 元素。
    • React 组件支持使用 renderItem 属性自定义渲染,接收 (index, itemData) 参数并返回 React 元素。
    • 使用核心类时,通过 onRenderItem 回调自定义渲染。
  4. 浏览器兼容性

    • 需要支持 IntersectionObserver API(现代浏览器都支持)。
    • 对于不支持的环境,会自动降级使用滚动事件。
  5. 依赖

    • 核心库依赖 lenis 用于平滑滚动。
    • Vue 组件需要 Vue 3.x。
    • React 组件需要 React 16.8+(支持 Hooks)。