React Native列表滚动卡顿怎么优化?
我在用FlatList渲染一个商品列表,数据大概有200条左右,但一滚动就明显卡顿,FPS掉得很厉害。已经加了keyExtractor和initialNumToRender,还是没改善。
是不是 renderItem 里组件太重了?我里面用了Image和Text,还套了几层View。下面是我现在的写法:
const renderItem = ({ item }) => (
<View style={{ padding: 16 }}>
<Image source={{ uri: item.image }} style={{ width: 80, height: 80 }} />
<Text>{item.title}</Text>
<Text>{item.price}</Text>
</View>
);
有没有什么办法能让列表滑动更流畅?比如该不该用React.memo或者优化图片加载?
先说renderItem的问题
你现在的写法每次滚动都会重新创建这些组件,React.memo必须用上。最简单的方式是把renderItem改成独立的组件,然后用memo包起来:
关于图片
如果图片加载慢,也会导致卡顿。可以考虑几个方案:给Image加个默认图或者loading状态、或者用react-native-fast-image这个库来缓存图片,会比原生Image快很多。
减少View嵌套
你说套了几层View,这个也有影响。你现在代码里其实嵌套不多,但如果父组件那边还有其他包装,能省则省。
关于getItemLayout
这个一定一定要加!它让FlatList不用每次去算每个item的高度,直接按索引跳到对应位置,滚动流畅度提升很明显。你需要提前把item的高度算出来传进去。
这几个一起用的话,200条数据流畅滚动基本没问题。你先试试,有问题再贴代码进来。
先说最直接有效的方案:用 React.memo 包装你的 Item 组件。
const ListItem = React.memo(({ item }) => (
));
const renderItem = ({ item }) =>
这样只有 item 的引用变化时才重新渲染,避免了每次滚动都触发 renderItem。
然后图片这块,如果你没做缓存处理,Image 组件每次渲染都会发起请求。生产环境建议用 react-native-fast-image 这个库,它带磁盘缓存,比原生 Image 强太多。
const ListItem = React.memo(({ item }) => (
style={{ width: 80, height: 80 }}
/>
));
还有几个 FlatList 的参数可以调一下:
renderItem={renderItem}
keyExtractor={item => item.id}
getItemLayout={(data, index) => ({
length: 112, // 你的item高度
offset: 112 * index,
index,
})}
maxToRenderPerBatch={10}
windowSize={10}
removeClippedSubviews={true}
/>
getItemLayout 是最重要的,加上这个 FlatList 就不用每次算高度了,能提升明显。maxToRenderPerBatch 和 windowSize 控制渲染批次,可以减少首屏渲染压力。
至于你问的该不该用 memo,答案是:该用。只要你的 Item 组件是独立的,都建议用 memo 包一下。200条数据本身不大,优化完应该能跑满60fps。