React 中如何实现无限滚动列表及遇到的问题

· 约 7 分钟读完

背景

无限滚动列表是指当列表滚动到底部时,自动加载更多数据,使无限滚动成为可能。在很多现代的 Web 应用程序中,无限滚动列表已经成为非常流行的 UI 设计风格。

React 是一个非常流行的前端框架,因此,在 React 中实现无限滚动列表是非常重要的知识。

实现

在 React 中,我们通常使用虚拟列表来实现无限滚动列表。这样做的好处是能够优化列表性能,避免加载大量的数据。

简单实现

下面是一个简单的无限滚动列表,使用了 React Hooks。

这个简单实现的基本原理是:

  • 使用 useState 声明当前列表数据和页面状态(是否在加载中);
  • 使用 useEffect 在组件挂载时发起第一次加载;
  • 监听滚动事件,在滚动到底部时加载更多数据;
  • 在列表底部显示加载状态。

高级实现

该方法的问题是,每次加载都会完全填充列表并导致性能问题。

更好的实现是,始终仅渲染列表可见部分。最好的方式是仅在顶部插入新数据或从底部删除旧数据。这使得列表始终保持与 ul 的变化一致,也可以最小化 DOM 操作。

这可以通过使用 React 的虚拟列表库 react-window 和 react-virtualized-auto-sizer 库来实现。

该实现使用 FixedSizeList 和 AutoSizer,可以自动适应视图大小,并减少不必要的 DOM 操作。

遇到的问题

性能问题

在传统的滚动列表中,当列表数目很大时,会导致性能问题,即长时间等待数据渲染。React 的虚拟列表技术可以避免这个问题,它只渲染当前可见的列表内容,不再任何其他地方渲染 DOM。

但是,实现虚拟列表也存在一些问题。例如,列表的新数据可以在列表的任何地方添加或删除,因此,我们无法使用无效高度的占位符来优化性能。当我们滚动页面时,所有元素的大小仍然需要进行计算。

另外,由于虚拟列表是面向动态注入的,当我们尝试调整元素时,虚拟列表实际上并不知道它的内容以及需要多少空间。GetEnumerator 方法返回一个枚举器,其中包含所有可见项目的索引。还要注意它只能显示区域的上/下元素。在这种情况下,如果我们提取一个区域,它会分配空间以缓存对同一方向的多个请求,从而占用更多的内存。

外观问题

测试中发现,在列表滚动时,页面上出现了一种反弹效果,在往上滑后,项立即出现。我们看到占位符,有大量远程数据而没有本地数据。

为了解决这个问题,需要在页面顶部和底部都加载一些额外的内容,例如顶部用于“加载中”消息和底部占用空间。当用户滚动到接近底部甚至到达底部时,足够的缓冲区将保证初始部分在滑动时不可见。这样,当滚动满足加载新数据的条件时,可以通过添加到底部而无需删除任何项。

小结

在 React 中实现无限滚动列表需要考虑列表性能和外观问题,使用虚拟列表可以解决这个问题。React Hooks 是一种方便快捷的实现方式,而使用 react-window 和 react-virtualized-auto-sizer 库更加高效。通过实现一个完整的无限滚动列表,我们还可以了解到虚拟列表的一些优化技术。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d5c527a941bf7134afd1eb