返回

前端长列表渲染优化实战

前端

前言

在项目中,我们或多或少都会经历一些长列表渲染的难题,比如:

  • 列表数据量过大,导致页面加载缓慢
  • 滚动列表时,列表项的渲染和销毁频繁发生,导致页面卡顿
  • 列表项的高度不固定,导致列表滚动时出现错位

为了解决这些问题,本文将为大家详细的解析这类场景的解决方案。内容相对易上手,并不涉及复杂的逻辑,效果立竿见影。还等什么呢,快来看看吧。

虚拟列表

虚拟列表是一种常见的长列表渲染优化技术。它的原理是只渲染当前视口内的列表项,而将其他列表项隐藏起来。当用户滚动列表时,虚拟列表会动态地将新的列表项渲染到视口中,并销毁旧的列表项。

虚拟列表的优点是:

  • 减少了渲染的开销,提高了页面加载速度
  • 减少了滚动列表时的卡顿
  • 解决了列表项高度不固定导致的错位问题

虚拟列表的缺点是:

  • 实现起来相对复杂
  • 可能存在一些兼容性问题

虚拟列表的实现

虚拟列表的实现有很多种,这里介绍一种使用 React 实现虚拟列表的方法。

首先,我们需要创建一个虚拟列表组件。这个组件可以是一个函数组件,也可以是一个类组件。

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

const VirtualList = ({ data, itemHeight, estimatedItemHeight }) => {
  const [startIndex, setStartIndex] = useState(0);
  const [endIndex, setEndIndex] = useState(0);
  const listRef = useRef(null);

  useEffect(() => {
    const list = listRef.current;
    const listHeight = list.clientHeight;
    const startIndex = Math.floor(listHeight / itemHeight);
    const endIndex = startIndex + Math.ceil(listHeight / estimatedItemHeight);
    setStartIndex(startIndex);
    setEndIndex(endIndex);
  }, []);

  useEffect(() => {
    const list = listRef.current;
    list.addEventListener('scroll', () => {
      const scrollTop = list.scrollTop;
      const startIndex = Math.floor(scrollTop / itemHeight);
      const endIndex = startIndex + Math.ceil(listHeight / estimatedItemHeight);
      setStartIndex(startIndex);
      setEndIndex(endIndex);
    });
  }, []);

  return (
    <div ref={listRef} style={{ overflow: 'auto', height: '100%' }}>
      {data.slice(startIndex, endIndex).map((item, index) => (
        <div key={index} style={{ height: itemHeight }}>
          {item}
        </div>
      ))}
    </div>
  );
};

export default VirtualList;

这个组件接收三个参数:

  • data:列表数据
  • itemHeight:列表项的高度
  • estimatedItemHeight:列表项的估计高度

startIndexendIndex状态变量用于保存当前视口内的列表项的索引范围。listRef引用保存了虚拟列表的 DOM 节点。

在组件的useEffect钩子中,我们计算了当前视口内的列表项的索引范围,并将其保存到startIndexendIndex状态变量中。我们还添加了一个滚动事件监听器,当用户滚动列表时,重新计算索引范围并更新状态变量。

在组件的render方法中,我们只渲染了当前视口内的列表项。

虚拟列表的优化

虚拟列表可以进一步优化,以提高性能。

  • 使用 windowing 策略 :windowing 策略是一种减少渲染开销的策略。它通过将列表项分成多个窗口,并只渲染当前视口内的窗口来实现。
  • 使用预渲染 :预渲染是一种在页面加载时预先渲染列表项的策略。这可以减少页面加载时间,并提高滚动列表时的流畅性。
  • 使用硬件加速 :硬件加速可以利用 GPU 来加速渲染。这可以进一步提高滚动列表时的流畅性。

无限滚动

无限滚动是一种常见的长列表渲染优化技术。它的原理是当用户滚动列表到底部时,自动加载更多数据并添加到列表中。

无限滚动的优点是:

  • 减少了用户的手动操作
  • 提高了用户体验

无限滚动的缺点是:

  • 可能会导致页面加载缓慢
  • 可能会导致滚动列表时出现卡顿

无限滚动的实现

无限滚动的实现有很多种,这里介绍一种使用 React 实现无限滚动的