一、先理解 FlatList 为什么会卡
FlatList 本质是一个“虚拟列表(VirtualizedList) ”,它的性能瓶颈主要来自:
- JS 线程计算压力
- 频繁 re-render
- 布局计算(measure)
- Bridge 通信(JS ↔ Native)
- 内存占用过大
二、核心优化手段(必会)
1️⃣ 控制渲染窗口(最关键)
<FlatList
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
/>
参数解释:
initialNumToRender:首屏渲染多少条maxToRenderPerBatch:每批渲染数量windowSize:渲染区域(单位:屏)
👉 推荐经验值:
initialNumToRender: 8~12
maxToRenderPerBatch: 8~16
windowSize: 5~10
📌 原理:减少一次性渲染数量,降低 JS 压力
2️⃣ 使用 getItemLayout(强烈推荐)
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
👉 适用于:item 高度固定
📌 作用:
- 跳过 measure(布局测量)
- scrollToIndex 更精准
- 减少卡顿
👉 这是性能优化里收益最大之一
3️⃣ 避免不必要的 re-render(核心)
✅ 使用 React.memo
const Item = React.memo(({ item }) => {
return <Text>{item.title}</Text>;
});
✅ keyExtractor 稳定
keyExtractor={(item) => item.id}
❌ 避免:
keyExtractor={(item, index) => index.toString()}
✅ renderItem 不要每次新建函数
const renderItem = useCallback(({ item }) => {
return <Item item={item} />;
}, []);
4️⃣ 使用 shouldComponentUpdate / memo
复杂 item 必做:
export default React.memo(Item, (prev, next) => {
return prev.item === next.item;
});
📌 避免整列表更新
5️⃣ 使用 removeClippedSubviews
<FlatList removeClippedSubviews />
📌 作用:
- 移除屏幕外组件
- 减少内存占用
⚠️ 注意:
- 有时候会导致闪烁(尤其动画)
6️⃣ 减少 renderItem 复杂度
❌ 不要在 render 里做:
- 复杂计算
- JSON 处理
- 大量逻辑判断
✅ 提前处理数据:
const processedData = useMemo(() => {
return data.map(...)
}, [data]);
7️⃣ 避免 inline style
❌
<View style={{ padding: 10 }} />
✅
const styles = StyleSheet.create({
item: { padding: 10 },
});
📌 减少重复创建对象
8️⃣ 分页 / 懒加载(必须)
onEndReached={loadMore}
onEndReachedThreshold={0.5}
📌 不要一次性加载几千条数据
9️⃣ 使用 ListHeaderComponent / ListFooterComponent
避免在外层包一层 ScrollView:
❌
<ScrollView>
<FlatList />
</ScrollView>
👉 直接用:
<FlatList
ListHeaderComponent={<Header />}
ListFooterComponent={<Footer />}
/>
🔟 控制更新频率(大数据场景)
extraData={selectedId}
📌 只在必要时触发更新
三、进阶优化(大厂级)
🚀 1. 使用 FlashList(性能碾压)
👉 Shopify 出的:
npm install @shopify/flash-list
import { FlashList } from "@shopify/flash-list";
📌 优势:
- 更少掉帧
- 更好的内存管理
- 自动优化布局
👉 在大数据场景建议直接替换 FlatList
🚀 2. RecyclerListView(极致优化)
👉 更底层:
- 完全自定义布局
- 适合超大数据(万级)
但:
👉 使用复杂度高
🚀 3. 使用 InteractionManager
延迟非关键渲染:
InteractionManager.runAfterInteractions(() => {
// 非关键任务
});
🚀 4. 避免频繁 setState
// ❌
setList([...list, newItem]);
// ✅ 批量更新
四、性能优化 checklist(实战必看)
你可以对照排查:
- 是否使用 getItemLayout?
- item 是否 memo?
- renderItem 是否 useCallback?
- key 是否稳定?
- 是否分页加载?
- 是否避免 inline object?
- windowSize 是否合理?
- 是否避免大对象传递?
- 是否减少 bridge 通信?
五、给你一个推荐配置(通用模板)
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={7}
removeClippedSubviews
getItemLayout={getItemLayout}
onEndReached={loadMore}
/>
六、总结一句话
👉 FlatList 优化本质就是:
减少渲染数量 + 减少重渲染 + 减少计算 + 减少通信