如何高效渲染10万条数据

渲染大量数据的几种优化方案

1. 虚拟列表(推荐)

使用 react-virtualizedreact-window 实现虚拟滚动:

import { FixedSizeList } from 'react-window';
import React from 'react';

interface ItemProps {
  index: number;
  style: React.CSSProperties;
}

const VirtualList: React.FC = () => {
  // 列表项渲染函数
  const Row = ({ index, style }: ItemProps) => (
    <div style={style}>
      Row {index}
    </div>
  );

  return (
    <FixedSizeList
      height={400}
      width={300}
      itemCount={100000}
      itemSize={35}
    >
      {Row}
    </FixedSizeList>
  );
};

export default VirtualList;

2. 分页加载

import { List, Button } from 'antd';
import React, { useState } from 'react';

const PagedList: React.FC = () => {
  const [page, setPage] = useState(1);
  const pageSize = 20;
  
  const loadMore = () => {
    setPage(prev => prev + 1);
  };

  return (
    <List
      dataSource={data.slice(0, page * pageSize)}
      renderItem={item => (
        <List.Item>{item}</List.Item>
      )}
      loadMore={
        <Button onClick={loadMore}>加载更多</Button>
      }
    />
  );
};

3. 时间分片

使用 requestAnimationFrame 进行时间分片渲染:

import React, { useEffect, useState } from 'react';

const TimeSlicing: React.FC = () => {
  const [list, setList] = useState<number[]>([]);
  
  useEffect(() => {
    // 总数据
    const total = 100000;
    // 每次渲染数量
    const once = 200;
    
    const render = (curTotal: number) => {
      if (curTotal >= total) return;
      
      // 计算当前需要渲染的数据
      const curList = new Array(once).fill(1).map((_, index) => curTotal + index);
      
      requestAnimationFrame(() => {
        setList(prev => [...prev, ...curList]);
        render(curTotal + once);
      });
    };
    
    render(0);
  }, []);

  return (
    <div>
      {list.map((item, index) => (
        <div key={index}>{item}</div>
      ))}
    </div>
  );
};

4. Web Worker

将数据处理放在 Worker 线程中:

self.onmessage = (e) => {
  const { data } = e;
  // 处理数据
  const result = processLargeData(data);
  self.postMessage(result);
};
import React, { useEffect, useState } from 'react';

const WorkerList: React.FC = () => {
  const [list, setList] = useState([]);

  useEffect(() => {
    const worker = new Worker('dataWorker.ts');
    
    worker.onmessage = (e) => {
      setList(e.data);
    };
    
    worker.postMessage(rawData);
    
    return () => worker.terminate();
  }, []);

  return (
    <div>
      {list.map(item => (
        <div key={item.id}>{item.content}</div>
      ))}
    </div>
  );
};

建议

  1. 优先使用虚拟列表,这是最有效的方案
  2. 根据业务场景选择合适的方案:
    • 列表项高度固定:使用 react-window
    • 高度不固定:使用 react-virtualized
    • 无限加载:结合虚拟列表和分页
  3. 注意性能优化:
    • 使用 React.memo 优化列表项渲染
    • 避免在列表项中使用复杂的状态管理
    • 合理使用 key 属性

其他

渲染十万条数据的方法之分批渲染
渲染十万条数据的方法之虚拟列表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值