如果我可以使用React Virtualized的Collection组件来解决我的问题,我有点困惑。我将尝试描述我正在做的事情:
我在页面上使用React Virtualized来显示两个列表/项目集合。我已经完成了第一个具有相同宽度和高度的项目的集合:
第一个系列非常直接且易于实施。 现在我正在处理包含不同大小图像的第二个集合。我希望单元格具有相同的高度但不同的宽度(当然取决于图像尺寸)。问题是行可能并不总是具有相同数量的单元格:
使用React Virtualized可以实现这一目标吗?如果是这样,我如何确定" cellSizeAndPositionGetter"中的位置?
答案 0 :(得分:1)
我最近使用react-virtualized
List
来显示固定高度,可变宽度图像卡的行,并且效果很好。
我的List
rowRenderer
使用了一系列图片卡元素。也就是说,一系列反应组件数组,如JSX。
请参阅我的最终函数cardsRows
,了解如何根据元素宽度和屏幕宽度构建行。
以下是它的外观:
希望这有帮助!
我的代码的一些片段:
import {AutoSizer, List} from 'react-virtualized';
...
updateDimensions() {
this.setState({
screenWidth: window.innerWidth,
});
}
componentDidMount() {
window.addEventListener("resize", this.updateDimensions);
}
componentDidUpdate(prevProps, prevState) {
const props = this.props;
const state = this.state;
if (JSON.stringify(props.imageDocs) !== JSON.stringify(prevProps.imageDocs) || state.screenWidth !== prevState.screenWidth)
this.setState({
cardsRows: cardsRows(props, state.screenWidth),
});
}
rowRenderer({key, index, style, isScrolling}) {
if (!this.state.cardsRows.length)
return '';
return (
<div id={index} title={this.state.cardsRows[index].length} key={key} style={style}>
{this.state.cardsRows[index]}
</div>
);
}
...
render() {
return (
<div style={styles.subMain}>
<AutoSizer>
{({height, width}) => (<List height={height}
rowCount={this.state.cardsRows.length}
rowHeight={164}
rowRenderer={this.rowRenderer}
width={width}
overscanRowCount={2}
/>
)}
</AutoSizer>
</div>
);
}
...
const cardsRows = (props, screenWidth) => {
const rows = [];
let rowCards = [];
let rowWidth = 0;
const distanceBetweenCards = 15;
for (const imageDoc of props.imageDocs) {
const imageWidth = getWidth(imageDoc);
if (rowWidth + distanceBetweenCards * 2 + imageWidth <= screenWidth) {
rowCards.push(cardElement(imageDoc));
rowWidth += distanceBetweenCards + imageWidth;
}
else {
rows.push(rowCards);
rowCards = [];
rowWidth = distanceBetweenCards;
}
}
if (rowCards.length) {
rows.push(rowCards);
}
return rows;
};
const styles = {
subMain: {
position: 'absolute',
display: 'block',
top: 0,
right: 0,
left: 0,
bottom: 0,
}
};