React Native 列表組件:FlashList、FlatList 及更多
在移動(dòng)開發(fā)中,高效展示數(shù)據(jù)列表至關(guān)重要。作為 React Native 開發(fā)者,我們可以使用多種強(qiáng)大的工具來完成這一任務(wù)。無論是 ScrollView
、SectionList
還是 FlatList
,React Native 都提供了一系列用于數(shù)據(jù)展示的組件。
然而,隨著數(shù)據(jù)集的增長(zhǎng)和性能需求的提高,我們需要更優(yōu)化的解決方案。這時(shí),Shopify 推出的 FlashList 應(yīng)運(yùn)而生,它相較于傳統(tǒng)的列表組件,在性能上帶來了顯著提升。
本文將帶你回顧 React Native 列表組件的演進(jìn)過程,探討 ScrollView
的局限性,以及 FlatList
、SectionList
的優(yōu)化點(diǎn),并深入了解最新的 FlashList 如何進(jìn)一步提升性能和開發(fā)體驗(yàn)。
React Native 列表組件的演進(jìn)
ScrollView
ScrollView
是 React Native 提供的最基礎(chǔ)的列表組件之一,適用于簡(jiǎn)單的列表展示。然而,它的局限性也較為明顯:它會(huì)一次性渲染所有子組件,即整個(gè)數(shù)據(jù)列表,不論數(shù)據(jù)量大小。
示例如下:
import { StyleSheet, Text, ScrollView } from 'react-native';
import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context';
const data = [
'Alice', 'Bob', 'Charlie', 'Diana', 'Edward', 'Fiona',
'George', 'Hannah', 'Ian', 'Jasmine', 'Kevin', 'Liam',
'Mia', 'Nathan', 'Olivia', 'Patrick', 'Quinn', 'Rebecca',
'Samuel', 'Tina', 'Quinn', 'Rebecca', 'Samuel', 'Tina',
];
const App = () => {
return (
<SafeAreaProvider>
<SafeAreaView style={styles.container} edges={['top']}>
<ScrollView>
{data.map((item, idx) => (
<Text key={idx} style={styles.item}>{item}</Text>
))}
</ScrollView>
</SafeAreaView>
</SafeAreaProvider>
);
};
export default App;
const styles = StyleSheet.create({
container: { flex: 1, paddingTop: 22 },
item: { padding: 10, fontSize: 18, height: 44 },
});
ScrollView
的輸出如下:
盡管這種方式簡(jiǎn)單直觀,但當(dāng)數(shù)據(jù)量過大時(shí),它會(huì)占用大量?jī)?nèi)存,因?yàn)?ScrollView
沒有虛擬化或惰性加載的功能,導(dǎo)致渲染速度變慢,影響性能。
FlatList
為了解決 ScrollView
處理大數(shù)據(jù)集時(shí)的性能瓶頸,React Native 引入了 FlatList
組件。它采用虛擬化渲染技術(shù),只渲染當(dāng)前屏幕內(nèi)可見的列表項(xiàng),而屏幕外的項(xiàng)會(huì)被移除,從而大幅節(jié)省內(nèi)存并提高渲染效率。
FlatList 的主要特性:
- 支持水平滾動(dòng)
- 可添加列表頭部和尾部
- 支持分隔符
- 下拉刷新
- 滾動(dòng)加載
- 支持
scrollToIndex
方法 - 支持多列布局
示例如下:
import { StyleSheet, Text, FlatList } from 'react-native';
import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context';
const data = [...]; // 省略數(shù)據(jù)
const App = () => {
return (
<SafeAreaProvider>
<SafeAreaView style={styles.container} edges={['top']}>
<FlatList
data={data}
keyExtractor={(_, index) => index.toString()}
renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
/>
</SafeAreaView>
</SafeAreaProvider>
);
};
export default App;
const styles = StyleSheet.create({
container: { flex: 1, paddingVertical: 22 },
item: { padding: 10, fontSize: 18, height: 44 },
});
與 ScrollView
不同,FlatList
具備 keyExtractor
屬性,可以自動(dòng)為數(shù)據(jù)項(xiàng)生成唯一的 key,從而優(yōu)化渲染效率。
SectionList
SectionList
與 FlatList
類似,但它額外支持分組數(shù)據(jù)展示,適用于需要按類別歸類的數(shù)據(jù)。例如,顯示菜單、通訊錄或分類列表時(shí),SectionList
更加合適。
SectionList 主要特性:
- 支持水平滾動(dòng)
- 支持列表頭部和尾部
- 支持分隔符
- 支持分類標(biāo)題
- 下拉刷新
- 滾動(dòng)加載
- 支持
scrollToIndex
方法 - 支持多列布局
示例如下:
import { StyleSheet, Text, SectionList, View } from 'react-native';
import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context';
const data = [
{ title: '主食', data: ['披薩', '漢堡', '燴飯'] },
{ title: '配菜', data: ['薯?xiàng)l', '洋蔥圈', '炸蝦'] },
{ title: '飲料', data: ['水', '可樂', '啤酒'] },
{ title: '甜點(diǎn)', data: ['芝士蛋糕', '冰淇淋'] },
];
const App = () => (
<SafeAreaProvider>
<SafeAreaView style={styles.container} edges={['top']}>
<SectionList
sections={data}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
renderSectinotallow={({ section: { title } }) => (
<Text style={styles.header}>{title}</Text>
)}
/>
</SafeAreaView>
</SafeAreaProvider>
);
export default App;
const styles = StyleSheet.create({
container: { flex: 1 },
item: { padding: 10, fontSize: 18 },
header: { padding: 10, fontSize: 20, backgroundColor: '#ddd' },
});
在 iOS 端,SectionList
的分組標(biāo)題默認(rèn)會(huì)固定在頂部,提升用戶體驗(yàn)。
FlashList
FlashList
由 Shopify 開發(fā),針對(duì)大規(guī)模數(shù)據(jù)列表進(jìn)行了極致優(yōu)化。它不僅保留了 FlatList
的 API 設(shè)計(jì),還提升了渲染速度,適用于超大數(shù)據(jù)集的高性能渲染。
FlashList 主要特性:
- 優(yōu)化渲染,速度提升 10 倍
- 流暢滾動(dòng),內(nèi)存占用更低
- API 兼容
FlatList
,遷移成本低
安裝 FlashList:
# 使用 yarn
yarn add @shopify/flash-list
# 使用 expo
npx expo install @shopify/flash-list
示例如下:
import { FlashList } from '@shopify/flash-list';
<FlashList
data={data}
renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
keyExtractor={(_, index) => index.toString()}
estimatedItemSize={20}
/>;
性能對(duì)比
組件 | 渲染方式 | 適用場(chǎng)景 | 性能表現(xiàn) |
ScrollView | 一次性渲染所有項(xiàng) | 小型數(shù)據(jù)集 | 差 |
FlatList | 虛擬化渲染 | 大型數(shù)據(jù)集 | 良好 |
SectionList | 虛擬化渲染 | 分類數(shù)據(jù)集 | 良好 |
FlashList | 高度優(yōu)化 | 超大數(shù)據(jù)集 | 優(yōu)異 |
總結(jié)
React Native 提供了豐富的列表組件,而 FlashList 以卓越的性能脫穎而出。如果你的應(yīng)用需要處理大量數(shù)據(jù),建議優(yōu)先考慮 FlashList,它能提供更加流暢的用戶體驗(yàn),同時(shí)無需大幅修改代碼。