FlatList

官方文檔 中文 React Native Express

以下內容來自官網高性能的列表組件 只渲染顯示於螢幕內的內容,只更新資料有變動的item 支持以下常用功能:

  • 完全跨平台

  • 水平佈局

  • 行組件顯示或隱藏時可配置回調事件

  • 列表的頭部組件

  • 列表的尾部組件

  • 自定義行間分隔線

  • 下拉刷新

  • 上拉加載

  • 跳轉到指定的index(第index個item)

    • 此方法必須設置getItemLayout。getItemLayout中需帶入每個item的高度,目前找到的都是固定item高度,若item的高度是動態的情況下..尚無頭緒..

    • length=>當前item的高度 offset=>目前總高度

      getItemLayout={(data, index) => (
       {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
      )}

例子

最簡單的例子

<FlatList
  data={[{key: 'a'}, {key: 'b'}]}
  renderItem={({item}) => <Text>{item.key}</Text>}
/>

較複雜的例子

演示如何利用PureComponent來進一步優化性能和減少bug產生的可能(這段需要了解shouldComponentUpdate的機制,以及Component和PureComponent的不同)

  • 對於MyListItem組件來說,其onPressItem屬性使用箭頭函數而非bind的方式進行綁定,使其不會在每次列表重新render時生成一個新的函數,從而保證了props的不變性(當然前提是id、selected和title也沒變),避免了觸發自身無謂的重新render。換句話說,如果你是用bind來綁定onPressItem,每次都會生成一個新的函數,導致props在===比較時返回false,從而觸發自身的一次不必要的重新render。

  • 給FlatList指定extraData={this.state}屬性,是為了保證state.selected變化時,能夠正確觸發FlatList的更新。如果不指定此屬性,則FlatList不會觸發更新,因為它是一個PureComponent,其props在===比較中沒有變化則不會觸發更新。

  • keyExtractor屬性指定使用id作為列表每一項的key。

class MyListItem extends React.PureComponent {
  _onPress = () => {
    this.props.onPressItem(this.props.id);
  };

  render() {
    return (
      <SomeOtherWidget
        {...this.props}
        onPress={this._onPress}
      />
    )
  }
}

class MyList extends React.PureComponent {
  state = {selected: (new Map(): Map<string, boolean>)};

  _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}
      />
    );
  }
}

給予的data若有變動,請使用...data 此方法給予新的data,通知flatlist資料有變動

sample code

import React, {Component} from 'react'
import {StyleSheet, View, FlatList, Text} from 'react-native'

var data = [
    {"id":1, title:"title-1"},
    {"id":2, title:"title-2"},
    {"id":3, title:"title-3"},
    {"id":4, title:"title-4"},
    {"id":5, title:"title-5"},
    {"id":6, title:"title-6"},
    {"id":7, title:"title-7"}
]
export default class RecordList extends Component {
  render() {
    return(
      <FlatList
        data={data}
        keyExtractor={(item, index) => item.id}
        renderItem={({item, index}) => <Text>{item.title}</Text>}
        ItemSeparatorComponent={() => this.separator()} 
        onEndReachedThreshold = {0.5}
        onEndReached={()=> {/*快到底了,要加載更多資料..等*/} }
        ListFooterComponent={() => this.footerComponent()}
       />
    );
  }

  separator() {
    return <View style={styles.separator} />
  }

  footerComponent() {
    return (
    <View style={styles.footerView}>
        <Text>最後一筆</Text>
    </View>
    )
  }

}

const styles = StyleSheet.create({
  separator: {
    height: 1,
    backgroundColor: 'red',
  },
  footerView: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

參考

Last updated