小编典典

ReactJS:双向双向滚动建模

reactjs

我们的应用程序使用无限滚动来浏览大量异构项目列表。有一些皱纹:

  • 对于我们的用户来说,通常有10,000个项目的列表,并且需要滚动3k +。
  • 这些都是丰富的项目,因此在浏览器性能变得无法接受之前,我们只能在DOM中拥有几百个。
  • 这些物品的高度各不相同。
  • 这些项目可能包含图像,我们允许用户跳转到特定日期。这很棘手,因为用户可以跳到列表中需要在视口上方加载图像的位置,这会在加载时将内容下推。无法处理意味着用户可能会跳到某个日期,但是随后又被转移到了更早的日期。

已知的不完整解决方案:

  • react-infinite-scroll)-这只是一个简单的“当我们触底时加载更多”组件。它不会剔除任何DOM,因此它将死于数千个项目上。

  • 带有React的滚动位置)-显示如何在顶部插入 底部插入(而不是同时插入)时存储和恢复滚动位置。

我不是在寻找完整解决方案的代码(尽管那会很棒。)相反,我正在寻找“ React
Way”来为这种情况建模。滚动位置是否处于状态?我应该跟踪什么状态以保留我在列表中的位置?我需要保持什么状态,以便在滚动到渲染内容的底部或顶部附近时触发新的渲染?


阅读 289

收藏
2020-07-22

共1个答案

小编典典

这是无限表和无限滚动方案的混合。我为此找到的最好的抽象如下:

总览

制作一个<List>包含 所有
子项数组的组件。由于我们不渲染它们,因此仅分配它们并丢弃它们确实很便宜。如果10k分配太大,则可以传递一个采用范围并返回元素的函数。

<List>
  {thousandelements.map(function() { return <Element /> })}
</List>

您的List组件将跟踪滚动位置是什么,并且仅渲染可见的子级。它在开始时添加了一个大的空div来伪造未渲染的先前项目。

现在,有趣的是,一旦Element渲染了一个组件,就可以测量其高度并将其存储在中List。这使您可以计算间隔物的高度,并知道应在视图中显示多少个元素。

图片

您是说图像加载时使一切“跳”下来。解决方案是在img标签中设置图像尺寸:<img src="..." width="100" height="58" />。这样,浏览器不必知道知道要显示的大小就可以等待下载。这需要一些基础架构,但确实值得。

如果您无法预先知道大小,则onload在图像上添加侦听器,并在图像加载时测量其显示的尺寸并更新存储的行高并补偿滚动位置。

跳到随机元素

如果您需要跳转到列表中的随机元素,这将需要一些滚动位置的技巧,因为您不知道中间元素的大小。我建议您执行的操作是平均已经计算出的元素高度,然后跳转到最后一个已知高度+(元素数*平均值)的滚动位置。

由于不完全正确,当您回到最后一个已知的良好位置时,它将引起问题。发生冲突时,只需更改滚动位置即可解决。这将稍微移动滚动条,但不会对其造成太大影响。

反应细节

您想为所有渲染的元素提供一个键,以便在渲染之间维护它们。有两种策略:(1)仅具有n个键(0、1、2,…
n),其中n是可以显示和使用其位置模为n的元素的最大数量。(2)每个元素具有不同的键。如果所有元素都共享相似的结构,则最好使用(1)重用其DOM节点。如果没有,则使用(2)。

我只有两个React状态:第一个元素的索引和要显示的元素数。当前滚动位置和所有元素的高度将直接附加到this。使用时,setState您实际上是在进行重新渲染,仅在范围更改时才发生。

这是使用我在此答案中描述的一些技术的无限列表示例。这将需要一些工作,但是React绝对是实现无限列表的好方法:)

2020-07-22