【问题标题】:Overlap of elements when using dynamic height List使用动态高度列表时的元素重叠
【发布时间】:2018-01-02 13:24:18
【问题描述】:

在渲染它的提要时,我遇到了与 Facebook 几乎相同的问题。一旦渲染了很多帖子,就会出现性能问题。经过一些研究,我发现 react-virtualized 非常棒,但我无法让它适用于我的应用程序。

这些是我面临的问题:

  1. 由于每个帖子都可以嵌入 iframe 或图像,因此一旦加载了这些项目,我就会从 CellMeasurer 触发 measure 回调。因此,某些项目似乎未对齐。每次调用 measure 回调时,我都尝试执行 parent.measureAllRows()parent.recomputeRowHeights() 以查看它是否会修复它,但它没有。
  2. 每个帖子都有一个可展开的部分,因此我需要重新计算它的高度。除了将 props 发送到组件之外,还有其他选择吗?

这是设置:

class VirtualPostList extends React.PureComponent {
  constructor(props, context) {
    super(props, context);
    this._cache = new ReactVirtualized.CellMeasurerCache({
      fixedWidth: true,
      defaultHeight: 400
    });
    this.rowRenderer = this.rowRenderer.bind(this);
  }


  rowRenderer({index, isScrolling, key, parent, style}) {
    return (
      <ReactVirtualized.CellMeasurer
        cache={this._cache}
        columnIndex={0}
        key={key}
        parent={parent}
        rowIndex={index}>
        {({measure}) => (
          <div key={key} style={style}>
            <Post onLoad={measure}/>
          </div>
        )}
      </ReactVirtualized.CellMeasurer>
    )
  }

  componentDidUpdate(){
    this.listComponent.recomputeRowHeights();
  }

  render() {
    const cache = this._cache;
    const rowCount = this.props.posts.length;
    const _this = this;
    return (
      <ReactVirtualized.WindowScroller>
        {({height, isScrolling, onChildScroll, scrollTop}) =>
          <ReactVirtualized.AutoSizer disableHeight>
            {({width}) =>
              <ReactVirtualized.List
                autoHeight
                isScrolling={isScrolling}
                height={height}
                width={width}
                rowCount={rowCount}
                deferredMeasurementCache={cache}
                rowHeight={cache.rowHeight}
                rowRenderer={this.rowRenderer}
                scrollTop={scrollTop}
                onScroll={onChildScroll}
                ref={(listComponent) => _this.listComponent = listComponent}
              />
            }
          </ReactVirtualized.AutoSizer>}
      </ReactVirtualized.WindowScroller>
    )
  }
}

重叠示例:

【问题讨论】:

  • 您确定您的onLoad 回调不会过早触发吗?如果您要创建一个复制品,我很乐意看一下 Plnkr。这应该可以正常工作。我想存在某种时间问题。
  • 感谢您的回答。你的图书馆很棒。我意识到在加载小头像时我没有触发onLoad 回调。也许就是这样。不过不确定。
  • 这可能与此有关,但我注意到性能显着下降。有没有一种简单的方法可以用 ReactMeasure 之类的组件替换当前的 CellMeasurer?我发现 ReactMeasure 更简单,因为它使用了调整大小的观察者。我看到您在 github 存储库中对此发表了评论。
  • 不客气。 :) 据我所知,CellMeasurer 应该非常适合与Grid 一起工作。如果您在正确的时间触发回调,不确定是什么让它变慢。在 react-virtualized 演示页面上,我在 ListCellMeasurer 中加载图像,并使用 onLoad 以类似的方式测量它们,它似乎表现得很好。
  • 感谢您再次回答!我可能会尝试分析性能问题,但我注意到即使存在 5 个元素,滚动也很慢。可能在我这边。我知道我使用的组件很重。但是,我的组件可以自行扩展,所以我对如何测量它们有疑问。除了每次触发度量回调之外,我是否可以遵循一种模式?这就是我提出 ReactMeasure 的原因,它侦听元素的调整大小事件,因此对测量的调用更容易

标签: javascript react-virtualized


【解决方案1】:

正如@brianvaughn 建议的那样,我并没有在我应该在每个地方调用measure 方法。这些变得有点样板且难以维护,因为元素不仅具有图像,而且可以自行扩展或收缩。

因为我想避免手动调用 measure,所以我像 ReactMeasure 一样将 ResizeObserver 附加到组件。之后,我把rowRenderer函数改成这样:

  rowRenderer({index, isScrolling, key, parent, style}) {
    return (
      <ReactVirtualized.CellMeasurer
        cache={this._cache}
        columnIndex={0}
        key={key}
        parent={parent}
        rowIndex={index}>
        {({measure}) => (
          <div key={key} style={style}>
            <ResizeObservable onResize={measure}>
              <Post/>
            </ResizeObservable>
          </div>
        )}
      </ReactVirtualized.CellMeasurer>
    )
  }

如您所见,每次调整大小时都会调用 measure 函数。这还包括加载图像或 iframe 的时间,因此无需手动调用它们

【讨论】:

  • 很酷的看到 react-virtualized 和 resize 观察者像这样一起使用。
  • 您能分享一下这个ResizeObservable 组件来自哪里吗?我在网上的任何地方都找不到。
  • 祝福你和你的后代
猜你喜欢
  • 1970-01-01
  • 2023-01-10
  • 2012-06-14
  • 2017-10-21
  • 1970-01-01
  • 1970-01-01
  • 2016-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多