“为什么我的商品列表看起来这么单调?” —— 当我们的电商App因为平铺直叙的列表布局导致用户停留时间不足时,我意识到需要引入瀑布流布局来提升视觉吸引力。本文将带你从零实现一个高性能的React Native瀑布流组件,支持动态高度、无限滚动和内存优化!
一、瀑布流核心原理
1.1 瀑布流特点
- 错落有致:元素高度不统一
- 自动填充:智能计算最优位置
- 高性能:支持大数据量渲染
- 响应式:适应不同屏幕尺寸
1.2 实现方案对比
方案 | 优点 | 缺点 |
---|---|---|
Flex布局 | 简单易用 | 无法实现真正瀑布流 |
双列绝对定位 | 性能较好 | 需要手动计算位置 |
Masonry组件 | 功能完善 | 依赖第三方库 |
FlashList | 性能最佳 | 需要适配 |
二、基础实现方案
2.1 使用Flex双列布局
const WaterfallLayout = ({ data }) => {
const [leftItems, rightItems] = useMemo(() => {
return data.reduce((acc, item, index) => {
acc[index % 2].push(item);
return acc;
}, [[], []]);
}, [data]);
return (
<View style={styles.container}>
<View style={styles.column}>
{leftItems.map(renderItem)}
</View>
<View style={styles.column}>
{rightItems.map(renderItem)}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
paddingHorizontal: 8,
},
column: {
flex: 1,
marginHorizontal: 4,
},
});
适用场景:简单布局,元素高度差异不大
三、高级实现方案
3.1 动态高度计算布局
const AdvancedWaterfall = ({ data }) => {
const [columns, setColumns] = useState([[], []]);
const columnHeights = useRef([0, 0]).current;
useEffect(() => {
const newColumns = [[], []];
data.forEach(item => {
// 获取图片宽高比,计算预估高度
const aspectRatio = item.width / item.height;
const estimatedHeight = ITEM_WIDTH / aspectRatio;
// 选择当前较矮的列
const targetCol = columnHeights[0] <= columnHeights[1] ? 0 : 1;
newColumns[targetCol].push(item);
columnHeights[targetCol] += estimatedHeight + MARGIN;
});
setColumns(newColumns);
}, [data]);
return (
<View style={styles.container}>
{columns.map((col, colIndex) => (
<View key={colIndex} style={styles.column}>
{col.map((item, index) => (
<WaterfallItem
key={item.id}
item={item}
onLayout={(height) => {
// 动态更新列高
columnHeights[colIndex] += height - (ITEM_WIDTH / (item.width / item.height));
}}
/>
))}
</View>
))}
</View>
);
};
3.2 使用FlashList实现
impor