滚动

时间:2016-05-05 11:19:48

标签: javascript performance reactjs react-virtualized

我有一个react-virtualized's无限滚动列表,(大多数设置是从this example复制的)。我正在为其提供rowRenderer函数,例如specs要求。如果rowRenderer函数非常轻量级(即返回一个非常基本的组件作为行),这可以正常工作。 但是我的RowComponent的呈现在某些属性上包含了一些Array.map。这不应该导致任何问题,除了在滚动时rowRenderer函数被称为 tens 或甚至数百次。这会导致性能问题,使滚动不够平滑。 到目前为止我试过了:

  1. 缓存我的rowRenderer这有效,但我不喜欢这个解决方案,因为它可能在将来引起问题。
  2. 使RowComponent的渲染功能纯净,并使用shouldComponentUpdate实施react-addons-shallow-compare。这略微改善了性能但还不够。
  3. this example中,每个滚动也会多次调用rowRenderer函数(由于函数非常轻量,因此没有执行问题),这让我相信这种行为是设计的。所以:
    缓存是一个很好的解决方案吗?有关如何将其与我的应用程序状态同步的任何建议(我使用redux进行状态管理)?我在文档中遗漏了哪些内容可以减少对rowRenderer的调用(滚动时我的行没有变化的原因)?

2 个答案:

答案 0 :(得分:4)

这里反应虚拟化的作者。

您的awk -F, '{delete a; for (i=1;i<=NF;i++) if ($i!="") if ($i in a) {print; next} else a[$i]}' file John,Smith,Smith,21 John,42,42,42 方法应该是轻量级的,因为正如您所发现的,当用户滚动时,它们可能会被快速调用。好消息是,由于浏览器在UI的单独线程中管理滚动,因此通常不会导致任何性能问题。如果有的话,您可能会在列表边缘看到一些空白/空白区域,表示您的渲染器无法跟上用户的滚动速度。

需要注意的一点是,如果将touch或wheel事件处理程序附加到react-virtualized组件或其DOM祖先之一,这将强制浏览器在main / UI线程中滚动。这肯定会导致缓慢。

我目前正在in the middle进行重大更新(version 7),除其他外,它会将命名参数传递给用户函数,例如rowRenderer。这将使我能够传递元信息(例如列表当前是否正在滚动),这可以使您能够推迟&#34; heavy&#34;滚动正在进行中的逻辑。不幸的是,在版本6中这是不可能的,除非你愿意像doron-zavelevsky所提到的那样使用超时。

修改:您可能会很高兴地了解到this commit细胞缓存已进入即将发布的第7版。

答案 1 :(得分:3)

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

考虑一下你快速滚动项目到底部的情况 - 完全填充你在那里滚动过去的所有项目是没有意义的。因此,您尽可能快地返回渲染结果 - 并在项目内等待〜200ms - 然后检查组件是否仍然安装并执行实际工作。

由于isMounted已过时,您可以在componentDidMount期间将变量设置为true,然后将componentWillUnmount设置为false。