虚拟列表react-virtualized使用(npm install react-virtualized)

时间:2025-04-10 17:26:00

1. 虚拟化列表 (List)

// 1. 虚拟化列表 (List)

import { List } from 'react-virtualized';
import 'react-virtualized/styles.css'; // 只导入一次样式

// 示例数据
const list = Array(1000).fill().map((_, index) => ({
    id: index,
    name: `Item ${index}`,
    description: `This is item number ${index} in the list`
}));

function Index() {
    const rowRenderer = ({ index, key, style }) => {
        const item = list[index];
        return (
            <div key={key} style={style} className="list-item">
                <h3>{item.name}</h3>
                <p>{item.description}</p>
            </div>
        );
    };

    return (
        <List
            width={600} // 列表宽度
            height={400} // 列表高度
            rowCount={list.length} // 总行数
            rowHeight={80} // 每行高度
            rowRenderer={rowRenderer} // 行渲染函数
            overscanRowCount={5} // 预渲染的行数
        />
    )
}

export default Index;



2. 可变高度列表 (CellMeasurer)

// 2. 可变高度列表 (CellMeasurer)


import { List, CellMeasurer, CellMeasurerCache } from 'react-virtualized';
import 'react-virtualized/styles.css';

// 可变高度数据
const variableData = Array(500).fill().map((_, index) => ({
    id: index,
    title: `Item ${index}`,
    content: `This is item ${index}. `.repeat(Math.floor(Math.random() * 10) + 1)
}));

function Index() {
    // 创建测量缓存
    const cache = new CellMeasurerCache({
        defaultHeight: 60,
        fixedWidth: true
    });

    const rowRenderer = ({ index, key, parent, style }) => {
        const item = variableData[index];

        return (
            <CellMeasurer
                key={key}
                cache={cache}
                parent={parent}
                columnIndex={0}
                rowIndex={index}
            >
                <div style={style} className="variable-item">
                    <h3>{item.title}</h3>
                    <p>{item.content}</p>
                </div>
            </CellMeasurer>
        );
    };

    return (
        <List
            width={600} // 列表宽度
            height={400} // 列表高度
            deferredMeasurementCache={cache}
            rowHeight={cache.rowHeight} // 每行高度
            rowCount={variableData.length} // 总行数
            rowRenderer={rowRenderer} // 行渲染函数
            overscanRowCount={3} // 预渲染的行数
        />
    )
}

export default Index;


3. 无限加载列表 - 高度固定

// 3. 无限加载列表 - 高度固定

import React, { useState } from 'react';
import { List, AutoSizer } from 'react-virtualized';
import 'react-virtualized/styles.css';

function InfiniteLoadingList() {
  const [items, setItems] = useState(
    Array(50).fill().map((_, i) => ({ id: i, name: `Item ${i}` }))
  );
  const [loading, setLoading] = useState(false);

  const loadMoreItems = () => {
    if (loading) return;
    
    setLoading(true);
    
    // 模拟API调用
    setTimeout(() => {
      const newItems = Array(50).fill().map((_, i) => ({
        id: items.length + i,
        name: `Item ${items.length + i}`
      }));
      
      setItems(prev => [...prev, ...newItems]);
      setLoading(false);
    }, 1000);
  };

  const isRowLoaded = ({ index }) => index < items.length;

  const rowRenderer = ({ index, key, style }) => {
    if (!isRowLoaded({ index })) {
      return (
        <div key={key} style={style} className="loading-row">
          Loading...
        </div>
      );
    }
    
    const item = items[index];
    return (
      <div key={key} style={style} className="list-item">
        {item.name}
      </div>
    );
  };

  const onRowsRendered = ({ stopIndex }) => {
    if (stopIndex >= items.length - 10 && !loading) {
      loadMoreItems();
    }
  };

  return (
    <div style={{ height: '500px', width: '100%' }}>
      <AutoSizer>
        {({ width, height }) => (
          <List
            width={width}
            height={height}
            rowCount={items.length + 1} // +1 for loading row
            rowHeight={50}
            rowRenderer={rowRenderer}
            onRowsRendered={onRowsRendered}
            overscanRowCount={5}
          />
        )}
      </AutoSizer>
      {loading && <div className="loading-indicator">Loading more items...</div>}
    </div>
  );
}

export default InfiniteLoadingList;

4. 无限加载列表 - 高度不固定

// 4. 无限加载列表 - 高度不固定