滚动时多次调用 VirtualScroll rowRenderer 方法

VirtualScroll rowRenderer method is called many times while scrolling

我有一个react-virtualized's infinite scroll list, (Most of the setup is copied from this example). I'm providing it with a rowRenderer function like the specs要求。如果 rowRenderer 函数是 非常 轻量级(即 returns 作为行的非常基本的组件),则此方法工作正常。 但是我的 RowComponent 的渲染包含一些 Array.map 在某些属性上。这应该不会造成任何问题,除了 rowRenderer 函数在滚动时被调用 tens 甚至 hundreds 次。这会导致性能问题,使滚动不够平滑。 到目前为止我试过:

  1. 缓存我的 rowRenderer 这行得通,但我不喜欢这个解决方案,因为它可能会在未来引起问题。
  2. 使我的 RowComponent 的渲染函数纯净并使用 react-addons-shallow-compare 实现 shouldComponentUpdate。这略微提高了性能,但还不够。

this example 中,rowRenderer 函数在每次滚动时也被调用多次(没有性能问题,因为该函数非常轻量级),这让我相信这种行为是设计使然。所以:
缓存是一个好的解决方案吗?关于如何将它与我的应用程序状态同步的任何建议(我使用 redux 进行状态管理)?我在文档中遗漏了什么可以减少对 rowRenderer 的调用(没有理由在滚动时更改我的行)?

根据我使用该库的经验(虽然我没有使用最新版本)- 这是设计使然。 这是有道理的 - 为了避免一次呈现所有列表 - 并允许您无限滚动 - 它每次都会要求您呈现当前查看的项目。 您的目标是优化渲染功能 - 正如您自己提到的那样。 可以改善您的整体体验的另一件事是检查并查看您的项目是否在其 componentDidMount 生命周期方法中包含一些复杂代码 - 或者 运行s post-render 的任何其他代码。如果是这种情况 - 您可以通过超时延迟这些计算来优化快速滚动 - 并且只让它们 运行 如果在超时过去时组件仍然安装。

考虑一下您快速滚动项目以到达底部的情况 - 完全填充您滚动经过的所有项目是没有意义的。因此,您 return 尽可能快地呈现结果 - 在项目内部等待约 200 毫秒 - 然后检查组件是否仍在安装并进行真正的工作。

由于 isMounted 已过时,您只需在 componentDidMount 期间将变量设置为 true 并在 componentWillUnmount 时返回 false。

这里是 react-virtualized 的作者。

您的 rowRenderer 方法应该是轻量级的,因为正如您发现的那样,当用户滚动时它们可能会被快速调用。好消息是——由于浏览器在与 UI 不同的线程中管理滚动,这通常不会导致任何性能问题。如果有的话,您可能会注意到滚动方向列表边缘的一些 empty/white space - 表明您的渲染器无法跟上用户的滚动速度。

需要注意的一个警告是,如果您将触摸或滚轮事件处理程序附加到反应虚拟化组件或其 DOM 祖先之一,这将强制浏览器在 main/UI线程。那肯定会导致速度变慢。

我目前是 in the middle of a major update (version 7),除其他事项外,它会将命名参数传递给 rowRenderer 等用户函数。这将使我能够传递元信息(例如列表当前是否正在滚动),这可以让您在滚动过程中推迟 "heavy" 逻辑。不幸的是,这在版本 6 中是不可能的,除非您愿意像 doron-zavelevsky 提到的那样使用超时。

编辑:您可能很高兴得知 this commit 单元格缓存已进入即将发布的第 7 版。