首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >分享一些React虚拟列表的实现方法

分享一些React虚拟列表的实现方法

原创
作者头像
小焱
发布2025-08-14 14:21:00
发布2025-08-14 14:21:00
18500
代码可运行
举报
文章被收录于专栏:前端开发前端开发
运行总次数:0
代码可运行

在 React 中实现虚拟列表(Virtual List)是优化长列表性能的关键技术,它通过只渲染可视区域内的项目来减少 DOM 节点数量,提升页面流畅度。以下是几种常见的实现方法:

代码语言:javascript
代码运行次数:0
运行
复制
import React, { useState, useRef, useEffect } from 'react';

const BasicVirtualList = ({
  items,          // 所有列表数据
  itemHeight = 50, // 每个项目的固定高度
  visibleCount = 10 // 可视区域可显示的项目数量
}) => {
  const [startIndex, setStartIndex] = useState(0);
  const listRef = useRef(null);
  const containerRef = useRef(null);

  // 计算可视区域内的项目范围
  const handleScroll = () => {
    if (!containerRef.current) return;
    
    // 滚动距离 / 项目高度 = 起始索引
    const scrollTop = containerRef.current.scrollTop;
    const newStartIndex = Math.floor(scrollTop / itemHeight);
    
    // 避免频繁更新
    if (newStartIndex !== startIndex) {
      setStartIndex(newStartIndex);
    }
  };

  // 计算需要渲染的项目(可视区域 + 缓冲区)
  const endIndex = Math.min(
    startIndex + visibleCount + 5, // 额外渲染5个作为缓冲区
    items.length
  );
  const visibleItems = items.slice(startIndex, endIndex);

  // 计算偏移量(让可视项目显示在正确位置)
  const offsetTop = startIndex * itemHeight;

  useEffect(() => {
    const container = containerRef.current;
    if (container) {
      container.addEventListener('scroll', handleScroll);
      return () => container.removeEventListener('scroll', handleScroll);
    }
  }, [startIndex]);

  return (
    <div
      ref={containerRef}
      style={{
        height: `${visibleCount * itemHeight}px`, // 可视区域高度
        overflow: 'auto',
        position: 'relative',
        border: '1px solid #ccc'
      }}
    >
      {/* 占位容器,维持滚动条高度 */}
      <div
        style={{
          height: `${items.length * itemHeight}px`,
          position: 'absolute',
          top: 0,
          left: 0,
          right: 0
        }}
      />
      
      {/* 实际渲染的项目区域 */}
      <div
        ref={listRef}
        style={{
          position: 'absolute',
          top: offsetTop,
          left: 0,
          right: 0
        }}
      >
        {visibleItems.map((item, index) => (
          <div
            key={item.id}
            style={{
              height: `${itemHeight}px`,
              padding: '12px',
              borderBottom: '1px solid #eee',
              boxSizing: 'border-box'
            }}
          >
            {item.content}
          </div>
        ))}
      </div>
    </div>
  );
};

export default BasicVirtualList;

1. 基础手动实现(核心原理)

手动计算可视区域内的项目,通过滚动事件动态更新渲染范围。

核心原理

  • 外层容器设置固定高度并开启滚动
  • 用一个占位元素撑开列表总高度,保证滚动条正常工作
  • 通过滚动位置计算需要显示的项目范围(startIndex
  • 只渲染可视区域内的项目,并通过 top 偏移到正确位置
  • 增加缓冲区(额外渲染几个项目)减少滚动时的闪烁

2. 基于动态高度的实现

对于高度不固定的项目,需要动态计算每个项目的高度并缓存。

核心改进

  • heights 缓存每个项目的实际高度
  • offsets 数组存储累计高度,快速计算任意位置的偏移量
  • 滚动时通过二分法(简化版)查找起始索引
  • 项目渲染后自动测量高度并更新缓存

3. 使用成熟的第三方库

对于复杂场景,推荐使用经过优化的成熟库:

react-window

轻量级虚拟列表库,专注于性能和简单API。

代码语言:jsx
复制
import { FixedSizeList as List } from 'react-window';

const ReactWindowList = ({ items }) => {
  const Row = ({ index, style }) => (
    <div style={style}>
      {items[index].content}
    </div>
  );

  return (
    <List
      height={500}       // 可视区域高度
      width="100%"       // 宽度
      itemCount={items.length} // 总项目数
      itemSize={50}      // 每个项目高度
    >
      {Row}
    </List>
  );
};
react-virtualized

功能更全面的库,支持网格、表格等复杂布局。

代码语言:jsx
复制
import { List } from 'react-virtualized';

const ReactVirtualizedList = ({ items }) => {
  const rowRenderer = ({ index, key, style }) => (
    <div key={key} style={style}>
      {items[index].content}
    </div>
  );

  return (
    <List
      height={500}
      width="100%"
      rowCount={items.length}
      rowHeight={50}
      rowRenderer={rowRenderer}
    />
  );
};
react-tiny-virtual-list

超轻量级实现,适合简单场景。

选择建议

  • 简单固定高度列表:基础手动实现或 react-window
  • 动态高度列表:动态高度实现或 react-virtualized
  • 复杂场景(网格、表格)react-virtualizedreact-window 的网格组件
  • 极致性能需求:考虑 Web Workers 处理大数据计算

虚拟列表的核心是减少DOM节点数量精准计算可视区域,实际项目中可根据列表复杂度和性能要求选择合适的实现方式。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 基础手动实现(核心原理)
  • 2. 基于动态高度的实现
  • 3. 使用成熟的第三方库
    • react-window
    • react-virtualized
    • react-tiny-virtual-list
  • 选择建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档