我如何告诉 Masonry 组件它的单元格已经改变了它们的高度?

How do I tell the Masonry component that its cells have changed their height?

我有一个 React 组件,它以网格模式显示一维项目列表。每个项目都具有相同的宽度和高度,并且位于三列内。可能有很多这样的东西,所以我决定使用 Masonry 组件试一试 react-virtualized,它似乎正是为这个用例而写的。它运作良好,但有一个警告:如果项目改变了它们的高度,我无法让 Masonry 注意到。

这是一个简化的例子:

constructor(props) {
    [...]
    this.cellMeasurerCache = new CellMeasurerCache({
        defaultHeight: this.state.height,
        fixedWidth: true,
    });

    this.cellPositioner = createMasonryCellPositioner({
        cellMeasurerCache: this.cellMeasurerCache,
        columnCount: 3,
        columnWidth: 250,
        spacer: 20,
    });
}

[...]

cellRenderer({ index, key, parent, style }) {
    return (
        <CellMeasurer
            cache={this.cellMeasurerCache}
            index={index}
            key={key}
            parent={parent}
        >
            <div style={style}>
                [...]
            </div>
        </CellMeasurer>
    );
}

resetMasonry() {
    this.cellMeasurerCache.clearAll();

    this.cellPositioner.reset({
        cache: this.cellMeasurerCache,
        columnCount: 3,
        columnWidth: 250,
        spacer: 20,
    });

    this.masonryRef.recomputeCellPositions();
}

render() {
    return (
        <AutoSizer>
            {({ height, width }) =>
                <Masonry
                    cellCount={this.state.list.length}
                    cellMeasurerCache={this.cellMeasurerCache}
                    cellPositioner={this.cellPositioner}
                    cellRenderer={this.cellRenderer}
                    height={height}
                    ref={this.setMasonryRef}
                    width={width}
                />
            }
        </AutoSizer>
    );
}

resetMasonry 当组件的高度状态改变时调用。我从几个 Whosebug 答案和其他资源中收集了当前代码,甚至查看了源代码,但没有任何效果。我注意到我没有告诉 cellMeasurerCache 或其他任何关于高度变化的信息,所以我真的不应该期望它能工作,但似乎没有办法在那里获取该信息,甚至无法通过实例化一个新 CellMeasurerCache.

顺便说一句,如果我在 cellPositioner.reset 内更改 columnWidth,Masonry 组件会相应更新,果然如此。

有人知道我缺少什么来让它工作以改变高度吗?谢谢!

如果您的 Masonry 单元格大小发生变化,您需要清除 CellMeasurerCache 中的缓存大小,然后确保 cellPositioner 也知道新的大小。例如:

// Clear cached measurements since sizes have changed:
cellMeasurerCache.clearAll()

// Let your component know it needs to re-render
this.setState({...}, () => {
  // Assuming you're using the default createCellPositioner()
  // Let it know of any values that may have changed:
  cellPositioner.reset({
    columnCount,
    columnWidth,
    spacer
  })

  // Tell Masonry to discard any cached position data:
  masonryRef.clearCellPositions()
})

您还可以在 RV site just by changing the column width. The source code for that demo is available in the GitHub repo 上看到一个 Masonry 组件的演示,它可以改变列的高度。

根据您的描述,我不建议使用 Masonry。我实际上只是建议以与我在这个例子中所做的类似的方式使用 Listhttp://plnkr.co/edit/zjCwNeRZ7XtmFp1PDBsc?p=preview

关键位是根据可用宽度动态计算每行的项目数,然后你给List一个调整后的rowCount:

  const itemsPerRow = Math.floor(width / ITEM_SIZE);
  const rowCount = Math.ceil(ITEMS_COUNT / itemsPerRow);