React Native 組件學習-FlatList

高性能的簡單列表組件,支持下面這些經常使用的功能:javascript

  • 徹底跨平臺。
  • 支持水平佈局模式。
  • 行組件顯示或隱藏時可配置回調事件。
  • 支持單獨的頭部組件。
  • 支持單獨的尾部組件。
  • 支持自定義行間分隔線。
  • 支持下拉刷新。
  • 支持上拉加載。
  • 支持跳轉到指定行(ScrollToIndex)。

若是須要分組/類/區(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 的不變性(固然前提是 idselectedtitle也沒變),不會觸發自身無謂的從新 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 中的基本類型和引用類型。)
  • 爲了優化內存佔用同時保持滑動的流暢,列表內容會在屏幕外異步繪製。這意味着若是用戶滑動的速度超過渲染的速度,則會先看到空白的內容。這是爲了優化不得不做出的妥協,你能夠根據本身的需求調整相應的參數,而咱們也在設法持續改進。
  • 默認狀況下每行都須要提供一個不重複的 key 屬性。你也能夠提供一個keyExtractor函數來生成 key。

本組件若是嵌套在其餘同滾動方向的 FlatList 中,則不會繼承ScrollView 的 Props


文檔

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}
  ...
複製代碼

minimumViewTime

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.

viewAreaCoveragePercentThreshold

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.

itemVisiblePercentThreshold

Similar to viewAreaPercentThreshold, but considers the percent of the item that is visible, rather than the fraction of the viewable area it covers.

waitForInteraction

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:

  • 'animated' (boolean) - Whether the list should do an animation while scrolling. Defaults to true.

scrollToIndex()

scrollToIndex(params);
複製代碼

將位於指定位置的元素滾動到可視區的指定位置,當viewPosition 爲 0 時將它滾動到屏幕頂部,爲 1 時將它滾動到屏幕底部,爲 0.5 時將它滾動到屏幕中央。

注意:若是不設置getItemLayout屬性的話,沒法跳轉到當前渲染區域之外的位置。

參數:

名稱 類型 必填 說明
params object 看下面的說明

Valid params keys are:

  • 'animated' (boolean) - Whether the list should do an animation while scrolling. Defaults to true.
  • 'index' (number) - The index to scroll to. Required.
  • 'viewOffset' (number) - A fixed number of pixels to offset the final target position. Required.
  • 'viewPosition' (number) - A value of 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:

  • 'animated' (boolean) - Whether the list should do an animation while scrolling. Defaults to true.
  • 'item' (object) - The item to scroll to. Required.
  • 'viewPosition' (number)

scrollToOffset()

scrollToOffset(params);
複製代碼

滾動列表到指定的偏移(以像素爲單位),等同於ScrollViewscrollTo方法。

參數:

名稱 類型 必填 說明
params object 看下面的說明

Valid params keys are:

  • 'offset' (number) - The offset to scroll to. In case of horizontal being true, the offset is the x-value, in any other case the offset is the y-value. Required.
  • 'animated' (boolean) - Whether the list should do an animation while scrolling. Defaults to true.

recordInteraction()

recordInteraction();
複製代碼

主動通知列表發生了一個事件,以使列表從新計算可視區域。好比說當waitForInteractions爲 true 而且用戶沒有滾動列表時。通常在用戶點擊了列表項或發生了導航動做時調用。


flashScrollIndicators()

flashScrollIndicators();
複製代碼

短暫地顯示滾動指示器。

相關文章
相關標籤/搜索