高性能的簡單列表組件,支持下面這些經常使用的功能:javascript
若是須要分組/類/區(section),請使用<SectionList>
.java
一個最簡單的例子:react
<FlatList
data={[{key: 'a'}, {key: 'b'}]}
renderItem={({item}) => <Text>{item.key}</Text>}
/>
複製代碼
下面是一個較複雜的例子,其中演示瞭如何利用PureComponent
來進一步優化性能和減小 bug 產生的可能(如下這段文字須要你深入理解 shouldComponentUpdate 的機制,以及 Component 和 PureComponent 的不一樣,因此若是不瞭解就先跳過吧)。android
對於MyListItem
組件來講,其onPressItem
屬性使用箭頭函數而非 bind 的方式進行綁定,使其不會在每次列表從新 render 時生成一個新的函數,從而保證了 props 的不變性(固然前提是 id
、selected
和title
也沒變),不會觸發自身無謂的從新 render。換句話說,若是你是用 bind 來綁定onPressItem
,每次都會生成一個新的函數,致使 props 在===
比較時返回 false,從而觸發自身的一次沒必要要的從新 render。git
給FlatList
指定extraData={this.state}
屬性,是爲了保證state.selected
變化時,可以正確觸發FlatList
的更新。若是不指定此屬性,則FlatList
不會觸發更新,由於它是一個PureComponent
,其 props 在===
比較中沒有變化則不會觸發更新。github
keyExtractor
屬性指定使用 id 做爲列表每一項的 key。segmentfault
class MyListItem extends React.PureComponent { _onPress = () => { this.props.onPressItem(this.props.id); };react-native
render() {
const textColor = this.props.selected ? "red" : "black";
return (
<TouchableOpacity onPress={this._onPress}>
<View>
<Text style={{ color: textColor }}>
{this.props.title}
</Text>
</View>
</TouchableOpacity>
);
}
複製代碼
}數組
class MultiSelectList extends React.PureComponent { state = {selected: (new Map(): Map<string, boolean>)};bash
_keyExtractor = (item, index) => item.id;
_onPressItem = (id: string) => {
// updater functions are preferred for transactional updates
this.setState((state) => {
// copy the map rather than modifying state.
const selected = new Map(state.selected);
selected.set(id, !selected.get(id)); // toggle
return {selected};
});
};
_renderItem = ({item}) => (
<MyListItem
id={item.id}
onPressItem={this._onPressItem}
selected={!!this.state.selected.get(item.id)}
title={item.title}
/>
);
render() {
return (
<FlatList
data={this.props.data}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
);
}
複製代碼
}
本組件實質是基於<VirtualizedList>
組件的封裝,繼承了其全部 props(也包括全部<ScrollView>
)的 props),但在本文檔中沒有列出。此外還有下面這些須要注意的事項:
PureComponent
而非一般的Component
,這意味着若是其props
在淺比較
中是相等的,則不會從新渲染。因此請先檢查你的renderItem
函數所依賴的props
數據(包括data
屬性以及可能用到的父組件的 state),若是是一個引用類型(Object 或者數組都是引用類型),則須要先修改其引用地址(好比先複製到一個新的 Object 或者數組中),而後再修改其值,不然界面極可能不會刷新。(譯註:這一段不瞭解的朋友建議先學習下js 中的基本類型和引用類型。)keyExtractor
函數來生成 key。本組件若是嵌套在其餘同滾動方向的 FlatList 中,則不會繼承ScrollView 的 Props。
renderItem
renderItem({ item: Object, index: number, separators: { highlight: Function, unhighlight: Function, updateProps: Function(select: string, newProps: Object) } }) => ?React.Element
複製代碼
從data
中挨個取出數據並渲染到列表中。
Provides additional metadata like index
if you need it, as well as a more generic separators.updateProps
function which let you set whatever props you want to change the rendering of either the leading separator or trailing separator in case the more common highlight
and unhighlight
(which set the highlighted: boolean
prop) are insufficient for your use case.
類型 | 必填 |
---|---|
function | 是 |
示例:
<FlatList
ItemSeparatorComponent={Platform.OS !== 'android' && ({highlighted}) => (
<View style={[style.separator, highlighted && {marginLeft: 0}]} /> )} data={[{title: 'Title Text', key: 'item1'}]} renderItem={({item, separators}) => ( <TouchableHighlight onPress={() => this._onPress(item)} onShowUnderlay={separators.highlight} onHideUnderlay={separators.unhighlight}> <View style={{backgroundColor: 'white'}}> <Text>{item.title}</Text> </View> </TouchableHighlight> )} /> 複製代碼
data
爲了簡化起見,data 屬性目前只支持普通數組。若是須要使用其餘特殊數據結構,例如 immutable 數組,請直接使用更底層的VirtualizedList
組件。
類型 | 必填 |
---|---|
array | 是 |
ItemSeparatorComponent
行與行之間的分隔線組件。不會出如今第一行以前和最後一行以後。 By default, highlighted
and leadingItem
props are provided. renderItem
provides separators.highlight
/unhighlight
which will update the highlighted
prop, but you can also add custom props with separators.updateProps
.
類型 | 必填 |
---|---|
component | 否 |
ListEmptyComponent
列表爲空時渲染該組件。能夠是 React Component, 也能夠是一個 render 函數,或者渲染好的 element。
類型 | 必填 |
---|---|
component, function, element | 否 |
ListFooterComponent
尾部組件。能夠是 React Component, 也能夠是一個 render 函數,或者渲染好的 element。
類型 | 必填 |
---|---|
component, function, element | 否 |
ListHeaderComponent
頭部組件。能夠是 React Component, 也能夠是一個 render 函數,或者渲染好的 element。
類型 | 必填 |
---|---|
component, function, element | 否 |
columnWrapperStyle
若是設置了多列布局(即將numColumns
值設爲大於 1 的整數),則能夠額外指定此樣式做用在每行容器上。
類型 | 必填 |
---|---|
style object | 否 |
extraData
若是有除data
之外的數據用在列表中(不管是用在renderItem
仍是頭部或者尾部組件中),請在此屬性中指定。同時此數據在修改時也須要先修改其引用地址(好比先複製到一個新的 Object 或者數組中),而後再修改其值,不然界面極可能不會刷新。
類型 | 必填 |
---|---|
any | 否 |
getItemLayout
(data, index) => {length: number, offset: number, index: number}
複製代碼
getItemLayout
是一個可選的優化,用於避免動態測量內容尺寸的開銷,不過前提是你能夠提早知道內容的高度。若是你的行高是固定的,getItemLayout
用起來就既高效又簡單,相似下面這樣:
getItemLayout={(data, index) => (
{length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
)}
複製代碼
對於元素較多的列表(幾百行)來講,添加getItemLayout
能夠極大地提升性能。注意若是你指定了ItemSeparatorComponent
,請把分隔線的尺寸也考慮到 offset 的計算之中。
類型 | 必填 |
---|---|
function | 否 |
horizontal
設置爲 true 則變爲水平佈局模式。
類型 | 必填 |
---|---|
boolean | 否 |
initialNumToRender
指定一開始渲染的元素數量,最好剛剛夠填滿一個屏幕,這樣保證了用最短的時間給用戶呈現可見的內容。注意這第一批次渲染的元素不會在滑動過程當中被卸載,這樣是爲了保證用戶執行返回頂部的操做時,不須要從新渲染首批元素。
類型 | 必填 |
---|---|
number | 否 |
initialScrollIndex
開始時屏幕頂端的元素是列表中的第 initialScrollIndex
個元素, 而不是第一個元素。若是設置了這個屬性,則第一批initialNumToRender
範圍內的元素不會再保留在內存裏,而是直接馬上渲染位於 initialScrollIndex
位置的元素。須要先設置 getItemLayout
屬性。
類型 | 必填 |
---|---|
number | 否 |
inverted
翻轉滾動方向。實質是將 scale 變換設置爲-1。
類型 | 必填 |
---|---|
boolean | 否 |
keyExtractor
(item: object, index: number) => string;
複製代碼
此函數用於爲給定的 item 生成一個不重複的 key。Key 的做用是使 React 可以區分同類元素的不一樣個體,以便在刷新時可以肯定其變化的位置,減小從新渲染的開銷。若不指定此函數,則默認抽取item.key
做爲 key 值。若item.key
也不存在,則使用數組下標。
類型 | 必填 |
---|---|
function | 否 |
numColumns
多列布局只能在非水平模式下使用,即必須是horizontal={false}
。此時組件內元素會從左到右從上到下按 Z 字形排列,相似啓用了flexWrap
的佈局。組件內元素必須是等高的——暫時還沒法支持瀑布流佈局。
類型 | 必填 |
---|---|
number | 否 |
onEndReached
(info: {distanceFromEnd: number}) => void
複製代碼
當列表被滾動到距離內容最底部不足onEndReachedThreshold
的距離時調用。
類型 | 必填 |
---|---|
function | 否 |
onEndReachedThreshold
決定當距離內容最底部還有多遠時觸發onEndReached
回調。注意此參數是一個比值而非像素單位。好比,0.5 表示距離內容最底部的距離爲當前列表可見長度的一半時觸發。
類型 | 必填 |
---|---|
number | 否 |
onRefresh
() => void
複製代碼
若是設置了此選項,則會在列表頭部添加一個標準的RefreshControl
控件,以便實現「下拉刷新」的功能。同時你須要正確設置refreshing
屬性。
類型 | 必填 |
---|---|
function | 否 |
onViewableItemsChanged
(info: {
viewableItems: array,
changed: array,
}) => void
複製代碼
在可見行元素變化時調用。可見範圍和變化頻率等參數的配置請設置viewabilityConfig
屬性。
類型 | 必填 |
---|---|
function | 否 |
progressViewOffset
當須要在指定的偏移處顯示加載指示器的時候,就能夠設置這個值。
類型 | 必填 | 平臺 |
---|---|---|
number | 否 | Android |
legacyImplementation
May not have full feature parity and is meant for debugging and performance comparison.
類型 | 必填 |
---|---|
boolean | 否 |
refreshing
在等待加載新數據時將此屬性設爲 true,列表就會顯示出一個正在加載的符號。
類型 | 必填 |
---|---|
boolean | 否 |
removeClippedSubviews
對於大列表啓用本屬性可能能夠提升性能。
注意:有些狀況下會有 bug(好比內容沒法顯示)。請謹慎使用。
類型 | 必填 |
---|---|
boolean | 否 |
viewabilityConfig
請參考ViewabilityHelper.js
的源碼來了解具體的配置。
類型 | 必填 |
---|---|
ViewabilityConfig | 否 |
viewabilityConfig
takes a type ViewabilityConfig
an object with following properties
Property | Required | Type |
---|---|---|
minimumViewTime | No | number |
viewAreaCoveragePercentThreshold | No | number |
itemVisiblePercentThreshold | No | number |
waitForInteraction | No | boolean |
At least one of the viewAreaCoveragePercentThreshold
or itemVisiblePercentThreshold
is required. This needs to be done in the constructor
to avoid following error (ref):
Error: Changing viewabilityConfig on the fly is not supported`
複製代碼
constructor (props) {
super(props)
this.viewabilityConfig = {
waitForInteraction: true,
viewAreaCoveragePercentThreshold: 95
}
}
複製代碼
<FlatList
viewabilityConfig={this.viewabilityConfig}
...
複製代碼
Minimum amount of time (in milliseconds) that an item must be physically viewable before the viewability callback will be fired. A high number means that scrolling through content without stopping will not mark the content as viewable.
Percent of viewport that must be covered for a partially occluded item to count as "viewable", 0-100. Fully visible items are always considered viewable. A value of 0 means that a single pixel in the viewport makes the item viewable, and a value of 100 means that an item must be either entirely visible or cover the entire viewport to count as viewable.
Similar to viewAreaPercentThreshold
, but considers the percent of the item that is visible, rather than the fraction of the viewable area it covers.
Nothing is considered viewable until the user scrolls or recordInteraction
is called after render.
viewabilityConfigCallbackPairs
List of ViewabilityConfig
/onViewableItemsChanged
pairs. A specific onViewableItemsChanged
will be called when its corresponding ViewabilityConfig
's conditions are met. 請參考ViewabilityHelper.js
的源碼來了解具體的配置。
類型 | 必填 |
---|---|
array of ViewabilityConfigCallbackPair | 否 |
scrollToEnd()
scrollToEnd([params]);
複製代碼
滾動到底部。若是不設置getItemLayout
屬性的話,可能會比較卡。
參數:
名稱 | 類型 | 必填 | 說明 |
---|---|---|---|
params | object | 否 | 看下面的說明 |
Valid params
keys are:
true
.scrollToIndex()
scrollToIndex(params);
複製代碼
將位於指定位置的元素滾動到可視區的指定位置,當viewPosition
爲 0 時將它滾動到屏幕頂部,爲 1 時將它滾動到屏幕底部,爲 0.5 時將它滾動到屏幕中央。
注意:若是不設置
getItemLayout
屬性的話,沒法跳轉到當前渲染區域之外的位置。
參數:
名稱 | 類型 | 必填 | 說明 |
---|---|---|---|
params | object | 是 | 看下面的說明 |
Valid params
keys are:
true
.0
places the item specified by index at the top, 1
at the bottom, and 0.5
centered in the middle.scrollToItem()
scrollToItem(params);
複製代碼
這個方法會順序遍歷元素。儘量使用scrollToIndex
代替。
注意:若是不設置
getItemLayout
屬性的話,沒法跳轉到當前渲染區域之外的位置。
參數:
名稱 | 類型 | 必填 | 說明 |
---|---|---|---|
params | object | 是 | 看下面的說明 |
Valid params
keys are:
true
.scrollToOffset()
scrollToOffset(params);
複製代碼
滾動列表到指定的偏移(以像素爲單位),等同於ScrollView
的scrollTo
方法。
參數:
名稱 | 類型 | 必填 | 說明 |
---|---|---|---|
params | object | 是 | 看下面的說明 |
Valid params
keys are:
horizontal
being true, the offset is the x-value, in any other case the offset is the y-value. Required.true
.recordInteraction()
recordInteraction();
複製代碼
主動通知列表發生了一個事件,以使列表從新計算可視區域。好比說當waitForInteractions
爲 true 而且用戶沒有滾動列表時。通常在用戶點擊了列表項或發生了導航動做時調用。
flashScrollIndicators()
flashScrollIndicators();
複製代碼
短暫地顯示滾動指示器。