React Native——組件FlatList

屬性

添加頭部組件

ListHeaderComponent屬性用來給FlatList添加頭部組件 
簡單使用:react

//ES6以前寫法
_header = function () {
  return (
    <Text style={{fontWeight: 'bold', fontSize: 20}}>熱門電影</Text>
  );
}


<FlatList
ListHeaderComponent={this._header}//header頭部組件
/>

 

添加尾部組件

ListFooterComponent屬性爲FlatList添加尾部組件,接收的參數跟ListHeaderComponent相同。android

//ES6的寫法
_footer = () => (
  <Text style={{fontSize: 14, alignSelf: 'center'}}>到底啦,沒有啦!</Text>
)

<FlatList
  ListFooterComponent={this._footer} //添加尾部組件
/>

 

添加頭部和尾部組件比較簡單,須要注意的就是上邊二者ES5和6寫法的區別!數組

添加分割線

ItemSeparatorComponent屬性能夠爲FlatList列表之間添加分割線。 
舉個例子:網絡

class ItemDivideComponent extends Component {
  render() {
    return (
      <View style={{height: 1, backgroundColor: 'skyblue'}}/>
    );
  }
};


<FlatList
  ItemSeparatorComponent={ItemDivideComponent}//分割線組件
/>

 

這裏咱們自定義了一個組件來設置分割線,固然咱們像添加頭部和尾部同樣,在內部聲明以後使用this._header的寫法也是能夠的!ide

設置空數據視圖

ListEmptyComponent屬性,能夠爲FlatList設置一個沒有數據的時候展現的視圖!,這個屬性能夠接收的參數類型比較多,能夠是React Component,也能夠是一個render函數,或者渲染好的element。 
因此設置空數據視圖不只能夠像前邊介紹的兩種方式之外,還能夠接收一個render函數。 
舉個例子:函數

createEmptyView() {
  return (
   <Text style={{fontSize: 40, alignSelf: 'center'}}>尚未數據哦!</Text>
  );
}

<FlatList
  ListEmptyComponent={this.createEmptyView()}
/>

 

設置item的key

在前一篇博客中,咱們的設置data的時候,是這樣的:flex

data={[
  {key: '大護法'},
  {key: '繡春刀II:修羅戰場'},
  ...         
]}

 

相似{key:你的數據value}這樣的形式,是由於咱們在設置data的時候,必需要爲item設置key屬性,不然會有一個黃色的警告彈出。並且咱們須要注意的是這裏每個item的key是惟一的!,若是按照這樣的寫法,咱們在數據中有重複的,好比{key: '大護法'},{key: '大護法'},這裏的大護法只會顯示一個,由於FlatList會認爲這是一條數據,由於key相同! 
那麼爲何會這樣? 
由於FlatList中有一個屬性:keyExtractor,用於爲給定的item生成一個不重複的key若不指定此函數,則默認抽取item.key做爲key值。若item.key也不存在,則使用數組下標index。由於前邊沒有指定該屬性,因此就把item.key做爲了key值,纔會認定兩個重複的數據是一條數據!優化

那麼通常地,咱們能夠這樣使用:this

_keyExtractor = (item, index) => index;

<FlatList
  keyExtractor={this._keyExtractor}
/>

 

這樣就把data中數組的下標做爲了惟一的key。 
那麼在data中指定數據的時候,就不用{key: '大護法'}這樣寫了,由於咱們已經指定了惟一的key,而能夠隨意寫{name: '大護法'}或者{movie: '大護法'},在渲染item的時候,取值用item.name或者item.movie便可!也不會有黃色的警告出現!spa

你明白了嗎?

設置itemLayout

getItemLayout屬性是一個可選的優化,用於避免動態測量內容尺寸的開銷。若是咱們知道item的高度,就能夠爲FlatList指定這一個屬性,來使FlatList更加高效的運行! 
舉個例子:

getItemLayout={(data, index) => ({
  length: 44, offset: (44 + 1) * index, index
})}

 

咱們在上邊使用的時候指定了item的高度爲44,因此length參數爲44;咱們設置了分割線,且指定分割線的高度是1,因此offset參數爲44+1。綜合來看,設置這個屬性應這樣寫:

getItemLayout={(data, index) => ({
  length: 你的item的height, offset: (你的item的height + ItemSeparator的height) * index, index
})}

 

設置這一屬性,在調用FlatList的跳轉函數的時候很是有用,不然可能會很卡頓!如scrollToEnd(),scrollToIndex(),這兩個方法後邊再說!

下拉刷新

FlatList中有兩個屬性,能夠用來設置下拉刷新。

  • refreshing在等待加載新數據時將此屬性設爲true,列表就會顯示出一個正在加載的符號.
  • onRefresh若是設置了此選項,則會在列表頭部添加一個標準的RefreshControl控件,以便實現「下拉刷新」的功能。同時你須要正確設置refreshing屬性。

這裏的RefreshControl控件,很是相似於Android v4包中的SwipeRefreshLayout,這裏就很少說了,須要瞭解的能夠查看相關文檔!

如何使用,舉個例子:

refreshing={this.state.refreshing}
onRefresh={() => {
  this.setState({refreshing: true})//開始刷新
  //這裏模擬請求網絡,拿到數據,3s後中止刷新
  setTimeout(() => {
    alert('沒有可刷新的內容!');
    this.setState({refreshing: false});//中止刷新
  }, 3000);
}}

 

上拉加載

關於上拉加載,FlatList也封裝有兩個屬性來實現:

  • onEndReachedThreshold:這個屬性決定當距離內容最底部還有多遠時觸發onEndReached回調。須要注意的是此參數是一個比值而非像素單位。好比,0.5表示距離內容最底部的距離爲當前列表可見長度的一半時觸發。因此它的取值範圍爲:(0,1),不包含0和1。
  • onEndReached:列表被滾動到距離內容最底部不足onEndReachedThreshold設置的的距離時調用。

具體使用,舉個例子:

onEndReachedThreshold={0.1}
onEndReached={({distanceFromEnd}) => (
  setTimeout(() => {
    this.setState((state) => ({
      data: state.data.concat(this._newData),
    }));
  }, 3000)
)}

 

這裏咱們設置的距離爲列表可見長度的1/10,而觸發了onEndReached函數時,咱們設置了一個定時器,3s後,將data中的數據添加了新數據,從而達到上拉加載更多的效果!

函數

介紹

FlatList下有兩個比較經常使用的函數:

scrollToEnd() 滾動到底部。若是不設置getItemLayout屬性的話,可能會比較卡。
scrollToIndex()若是不設置getItemLayout屬性的話,沒法跳轉到當前可視區域之外的位置。

 

如官方所言,使用這兩個函數的時候,最好指定設置getItemLayout屬性

使用

由於這兩個是FlatList組件的函數,因此在使用這兩個函數以前,首先咱們要獲得FlatList組件的引用。 
這時候就須要ref屬性react提供的這個ref屬性,表示爲對組件真正實例的引用。 
關於ref屬性的使用,能夠去React官網查看API!

具體的使用:

ref={(flatList) => this._flatList = flatList}


this._flatList.scrollToEnd();

//viewPosition參數:0表示頂部,0.5表示中部,1表示底部
this._flatList.scrollToIndex({viewPosition: 0, index: this.state.text});

 

至此,關於FlatList進階的相關基礎內容就說完了!

完整的Demo

class FlatListTest extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: this._sourceData,
      refreshing: false, //初始化不刷新
      text: ''//跳轉的行
    };
  }

  _header = function () {
    return (
      <Text style={{fontWeight: 'bold', fontSize: 20}}>熱門電影</Text>
    );
  }

  _footer = () => (
    <Text style={{fontSize: 14, alignSelf: 'center'}}>到底啦,沒有啦!</Text>
  )

  createEmptyView() {
    return (
      <Text style={{fontSize: 40, alignSelf: 'center'}}>尚未數據哦!</Text>
    );
  }

  //此函數用於爲給定的item生成一個不重複的key
  //若不指定此函數,則默認抽取item.key做爲key值。若item.key也不存在,則使用數組下標index。
  _keyExtractor = (item, index) => index;

  itemClick(item, index) {
    alert('點擊了第' + index + '項,電影名稱爲:' + item.name);
  }

  _renderItem = ({item, index}) => {
    return (
      <TouchableOpacity
        activeOpacity={0.5}
        onPress={this.itemClick.bind(this, item, index)}>
        <Text style={flatListStyles.item}>{item.name}</Text>
      </TouchableOpacity>
    );
  }

  //點擊按鈕跳轉
  onButtonPress() {
    //viewPosition參數:0表示頂部,0.5表示中部,1表示底部
    this._flatList.scrollToIndex({viewPosition: 0, index: this.state.text});
    //this._flatList.scrollToOffset({ animated: true, offset: 2000 });
  };

  onBtnPress2Botton() {
    this._flatList.scrollToEnd();
  }

  _sourceData = [
    {name: '大護法'},
    {name: '繡春刀II:修羅戰場'},
    {name: '神偷奶爸3'},
    {name: '神奇女俠'},
    {name: '摔跤吧,爸爸'},
    {name: '悟空傳'},
    {name: '閃光少女'},
    {name: '攻殼機動隊'},
    {name: '速度與激情8'},
    {name: '蝙蝠俠大戰超人'},
    {name: '攻殼機動隊'},
    {name: '速度與激情8'},
    {name: '蝙蝠俠大戰超人'}
  ]

  _newData = [{name: '我是新添加的數據1'},
    {name: '我是新添加的數據2'},
    {name: '我是新添加的數據3'}]

  render() {
    return (
      <View style={flatListStyles.container}>
        <View style={{flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}>
          <TextInput
            style={{flex: 1}}
            placeholder="請輸入要跳轉的行號"
            onChangeText={(text) => this.setState({text})}
          />
          <Button title="跳轉到行" onPress={this.onButtonPress.bind(this)} color={'skyblue'}/>
          <Button title="跳轉到底部" onPress={this.onBtnPress2Botton.bind(this)} color={'green'}/>

        </View>
        <FlatList
          data={this.state.data}
          //使用 ref 能夠獲取到相應的組件
          ref={(flatList) => this._flatList = flatList}
          ListHeaderComponent={this._header}//header頭部組件
          ListFooterComponent={this._footer}//footer尾部組件
          ItemSeparatorComponent={ItemDivideComponent}//分割線組件
          //空數據視圖,能夠是React Component,也能夠是一個render函數,或者渲染好的element。
          ListEmptyComponent={this.createEmptyView()}
          keyExtractor={this._keyExtractor}
          //是一個可選的優化,用於避免動態測量內容尺寸的開銷,不過前提是你能夠提早知道內容的高度。
          //若是你的行高是固定的,getItemLayout用起來就既高效又簡單.
          //注意若是你指定了SeparatorComponent,請把分隔線的尺寸也考慮到offset的計算之中
          getItemLayout={(data, index) => ( {length: 44, offset: (44 + 1) * index, index} )}
          //決定當距離內容最底部還有多遠時觸發onEndReached回調。
          //注意此參數是一個比值而非像素單位。好比,0.5表示距離內容最底部的距離爲當前列表可見長度的一半時觸發。
          onEndReachedThreshold={0.1}
          //當列表被滾動到距離內容最底部不足onEndReachedThreshold的距離時調用
          onEndReached={({distanceFromEnd}) => (
            setTimeout(() => {
              this.setState((state) => ({
                data: state.data.concat(this._newData),
              }));
            }, 3000)
          )}
          refreshing={this.state.refreshing}
          onRefresh={() => {
            this.setState({refreshing: true})//開始刷新
            //這裏模擬請求網絡,拿到數據,3s後中止刷新
            setTimeout(() => {
              alert('沒有可刷新的內容!');
              this.setState({refreshing: false});
            }, 3000);
          }}
          renderItem={this._renderItem}
        />
      </View>
    );
  }
}
;

class ItemDivideComponent
  extends Component {
  render() {
    return (
      <View style={{height: 1, backgroundColor: 'skyblue'}}/>
    );
  }
}
;

const flatListStyles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 22
  },
  item: {
    padding: 10,
    fontSize: 18,
    height: 44,
  },
})

AppRegistry.registerComponent('AwesomeProject', () => FlatListTest);
相關文章
相關標籤/搜索