当前位置:首页 > React

react实现虚拟列表

2026-01-26 22:14:40React

虚拟列表的概念

虚拟列表是一种优化长列表渲染性能的技术,通过仅渲染可视区域内的列表项,减少DOM节点数量和内存占用。适用于需要展示大量数据的场景,如聊天记录、表格数据等。

实现虚拟列表的关键步骤

计算可视区域高度和滚动位置 获取容器元素的高度和当前的滚动位置,确定需要渲染的列表项范围。使用useRefuseEffect监听滚动事件。

const containerRef = useRef(null);
const [scrollTop, setScrollTop] = useState(0);

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

计算可见项的起始和结束索引 根据滚动位置、列表项高度和可视区域高度,计算需要渲染的列表项范围。使用useMemo优化计算性能。

const itemHeight = 50; // 假设每个列表项高度固定
const visibleCount = Math.ceil(containerHeight / itemHeight);
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = startIndex + visibleCount;

渲染可见项 根据计算的起始和结束索引,截取对应的数据子集进行渲染。使用绝对定位控制列表项的位置。

const visibleItems = data.slice(startIndex, endIndex).map((item, index) => (
  <div 
    key={item.id}
    style={{
      position: 'absolute',
      top: `${(startIndex + index) * itemHeight}px`,
      height: `${itemHeight}px`,
      width: '100%'
    }}
  >
    {item.content}
  </div>
));

设置容器和占位元素 容器需要设置固定高度和overflow: auto,占位元素用于撑开滚动区域。

<div 
  ref={containerRef}
  style={{ height: '500px', overflow: 'auto' }}
>
  <div style={{ height: `${data.length * itemHeight}px`, position: 'relative' }}>
    {visibleItems}
  </div>
</div>

动态高度虚拟列表的实现

对于高度不固定的列表项,需要预先测量或估算高度,并维护一个位置缓存。

测量实际高度 在列表项渲染后,使用ResizeObservergetBoundingClientRect获取实际高度,并更新位置缓存。

const [positions, setPositions] = useState([]);
const itemRefs = useRef([]);

useEffect(() => {
  const newPositions = [];
  let totalHeight = 0;
  data.forEach((item, index) => {
    const height = itemRefs.current[index]?.getBoundingClientRect().height || estimatedHeight;
    newPositions.push({
      height,
      top: totalHeight,
      bottom: totalHeight + height
    });
    totalHeight += height;
  });
  setPositions(newPositions);
}, [data]);

根据位置缓存计算可见项 使用二分查找快速定位起始和结束索引。

const getStartIndex = (scrollTop) => {
  let low = 0, high = positions.length - 1;
  while (low <= high) {
    const mid = Math.floor((low + high) / 2);
    if (positions[mid].bottom < scrollTop) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }
  return low;
};

性能优化建议

使用React.memo避免不必要的列表项重渲染,对于复杂列表项组件尤其有效。

const MemoizedItem = React.memo(function Item({ item }) {
  return <div>{item.content}</div>;
});

滚动事件使用节流(throttle)或防抖(debounce)减少计算频率,平衡性能与流畅度。

const handleScroll = throttle(() => {
  setScrollTop(containerRef.current.scrollTop);
}, 16);

现有库推荐

对于快速实现,可考虑以下成熟库:

  • react-window: 提供固定高度和动态高度虚拟列表组件
  • react-virtualized: 功能更全面,支持表格、网格等复杂布局
  • react-virtuoso: 支持动态高度、分组等高级功能

react实现虚拟列表

标签: 列表react
分享给朋友:

相关文章

react 如何执行

react 如何执行

安装 Node.js 和 npm React 开发需要 Node.js 环境,因为它提供了 npm(或 yarn)包管理工具。从 Node.js 官网 下载并安装最新 LTS 版本。安装完成后,在终端…

react如何收录

react如何收录

React 收录方法 React 的收录主要涉及搜索引擎优化(SEO)和预渲染技术。由于 React 是单页应用(SPA),默认情况下内容由 JavaScript 动态生成,可能导致搜索引擎爬虫难以收…

react如何遍历

react如何遍历

遍历数组或对象的方法 在React中,遍历数组或对象通常用于渲染列表或动态生成内容。以下是几种常见的遍历方法: 使用map遍历数组map是遍历数组并返回新数组的高阶函数,适合渲染列表。 c…

react如何循环

react如何循环

循环渲染列表 在React中循环渲染列表通常使用map方法,这是最常用的方式。通过map可以将数组中的每个元素转换为React元素并渲染到页面上。 const items = ['Apple', '…

react就业如何

react就业如何

React 就业市场现状 React 作为当前主流前端框架之一,就业需求持续旺盛。国内外互联网企业、中大型公司以及初创团队普遍采用 React 技术栈,尤其在 Web 应用、移动端(React Nat…

react如何扩展

react如何扩展

扩展 React 项目的常用方法 使用高阶组件(HOC) 高阶组件是一种复用组件逻辑的方式。通过包裹组件并注入额外属性或逻辑,可以实现功能扩展。例如,一个日志记录的高阶组件: function…