React Virtualized Masonry 不会随浏览器调整大小
React Virtualized Masonry does not resize with the browser
我正在尝试建立一个提要(一个类似 Pinterest 的提要,直截了当)。我正在使用 react-virtualized
Masonry 组件。
您可以在 this 屏幕录制中看到当浏览器 window 调整大小时项目如何重新排列以及组件如何正确调整大小。
但是,正如您在 this 屏幕录制中看到的那样,我的行为很奇怪。
这是我的代码的相关摘录:
export default class Feed extends Component <PropTypes, State> {
static readonly defaultProps = {
enableInfiniteScroll: false,
chunkSize: 9,
};
private _windowScroller: WindowScroller;
private _masonry: Masonry;
private _columnCount: number;
private _cache: CellMeasurerCache;
private _cellPositioner: Positioner;
constructor(props: PropTypes) {
super(props);
// ...
this._columnCount = 3;
this._cache = new CellMeasurerCache({
defaultWidth: COLUMN_WIDTH,
defaultHeight: 400,
fixedWidth: true,
});
this._cellPositioner = createMasonryCellPositioner({
cellMeasurerCache: this._cache,
columnCount: this._columnCount,
columnWidth: COLUMN_WIDTH,
spacer: GUTTER,
});
}
onResize({width}: Size) {
this._cache.clearAll();
this.calculateColumnCount(width);
this.resetCellPositioner();
this._masonry.recomputeCellPositions();
}
cellRenderer(cellProps: MasonryCellProps) {
const {items} = this.state;
const listing = items.get(cellProps.index);
return (
<CellMeasurer
cache={this._cache}
index={cellProps.index}
key={cellProps.key}
parent={cellProps.parent}
>
<div style={cellProps.style}>
<ListingCard company={listing} />
</div>
</CellMeasurer>
);
}
calculateColumnCount(width: number) {
this._columnCount = Math.floor((width + GUTTER) / (COLUMN_WIDTH + GUTTER));
}
resetCellPositioner() {
this._cellPositioner.reset({
columnCount: this._columnCount,
columnWidth: COLUMN_WIDTH,
spacer: GUTTER,
});
}
render() {
const {items, isLoading, hasMore} = this.state;
return (
<div className={Styles['listings-feed']}>
<WindowScroller scrollElement={window} ref={this.setRef}>
{({height, isScrolling, onChildScroll, scrollTop, registerChild}) => (
<div className={Styles.windowScrollerContainer}>
<AutoSizer disableHeight onResize={this.onResize}>
{({width}) => (
<div ref={registerChild as any}>
<Masonry
cellCount={items.size}
cellMeasurerCache={this._cache}
cellPositioner={this._cellPositioner}
cellRenderer={this.cellRenderer}
height={height}
width={width}
autoHeight
ref={(r: Masonry) => this._masonry = r}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
</div>
);
}
}
在使用不同的参数和调整进行测试后,我发现并没有渲染所有项目,因为它们在技术上超出了范围(不在用户的视野中)。滚动时它们并没有超出视野,只是 <Masonry />
组件仅在 属性 更改时更新。
由于我使用的是 <WindowScroller />
组件,我发现它为 children
函数提供了一个 scrollTop
变量,所以我将其直接传递给了 Masonry
组件:
<WindowScroller scrollElement={window} ref={this.setRef}>
{({height, isScrolling, onChildScroll, scrollTop, registerChild}) => (
<div className={Styles.windowScrollerContainer}>
<AutoSizer disableHeight onResize={this.onResize}>
{({width}) => (
<div ref={registerChild as any}>
<Masonry
cellCount={items.size}
cellMeasurerCache={this._cache}
cellPositioner={this._cellPositioner}
cellRenderer={this.cellRenderer}
height={height}
width={width}
autoHeight
ref={(r: Masonry) => this._masonry = r}
scrollTop={scrollTop}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
我正在尝试建立一个提要(一个类似 Pinterest 的提要,直截了当)。我正在使用 react-virtualized
Masonry 组件。
您可以在 this 屏幕录制中看到当浏览器 window 调整大小时项目如何重新排列以及组件如何正确调整大小。
但是,正如您在 this 屏幕录制中看到的那样,我的行为很奇怪。
这是我的代码的相关摘录:
export default class Feed extends Component <PropTypes, State> {
static readonly defaultProps = {
enableInfiniteScroll: false,
chunkSize: 9,
};
private _windowScroller: WindowScroller;
private _masonry: Masonry;
private _columnCount: number;
private _cache: CellMeasurerCache;
private _cellPositioner: Positioner;
constructor(props: PropTypes) {
super(props);
// ...
this._columnCount = 3;
this._cache = new CellMeasurerCache({
defaultWidth: COLUMN_WIDTH,
defaultHeight: 400,
fixedWidth: true,
});
this._cellPositioner = createMasonryCellPositioner({
cellMeasurerCache: this._cache,
columnCount: this._columnCount,
columnWidth: COLUMN_WIDTH,
spacer: GUTTER,
});
}
onResize({width}: Size) {
this._cache.clearAll();
this.calculateColumnCount(width);
this.resetCellPositioner();
this._masonry.recomputeCellPositions();
}
cellRenderer(cellProps: MasonryCellProps) {
const {items} = this.state;
const listing = items.get(cellProps.index);
return (
<CellMeasurer
cache={this._cache}
index={cellProps.index}
key={cellProps.key}
parent={cellProps.parent}
>
<div style={cellProps.style}>
<ListingCard company={listing} />
</div>
</CellMeasurer>
);
}
calculateColumnCount(width: number) {
this._columnCount = Math.floor((width + GUTTER) / (COLUMN_WIDTH + GUTTER));
}
resetCellPositioner() {
this._cellPositioner.reset({
columnCount: this._columnCount,
columnWidth: COLUMN_WIDTH,
spacer: GUTTER,
});
}
render() {
const {items, isLoading, hasMore} = this.state;
return (
<div className={Styles['listings-feed']}>
<WindowScroller scrollElement={window} ref={this.setRef}>
{({height, isScrolling, onChildScroll, scrollTop, registerChild}) => (
<div className={Styles.windowScrollerContainer}>
<AutoSizer disableHeight onResize={this.onResize}>
{({width}) => (
<div ref={registerChild as any}>
<Masonry
cellCount={items.size}
cellMeasurerCache={this._cache}
cellPositioner={this._cellPositioner}
cellRenderer={this.cellRenderer}
height={height}
width={width}
autoHeight
ref={(r: Masonry) => this._masonry = r}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>
</div>
);
}
}
在使用不同的参数和调整进行测试后,我发现并没有渲染所有项目,因为它们在技术上超出了范围(不在用户的视野中)。滚动时它们并没有超出视野,只是 <Masonry />
组件仅在 属性 更改时更新。
由于我使用的是 <WindowScroller />
组件,我发现它为 children
函数提供了一个 scrollTop
变量,所以我将其直接传递给了 Masonry
组件:
<WindowScroller scrollElement={window} ref={this.setRef}>
{({height, isScrolling, onChildScroll, scrollTop, registerChild}) => (
<div className={Styles.windowScrollerContainer}>
<AutoSizer disableHeight onResize={this.onResize}>
{({width}) => (
<div ref={registerChild as any}>
<Masonry
cellCount={items.size}
cellMeasurerCache={this._cache}
cellPositioner={this._cellPositioner}
cellRenderer={this.cellRenderer}
height={height}
width={width}
autoHeight
ref={(r: Masonry) => this._masonry = r}
scrollTop={scrollTop}
/>
</div>
)}
</AutoSizer>
</div>
)}
</WindowScroller>