1. 程式人生 > 其它 >基礎篇章:關於 React Native 之 ListView 元件的講解

基礎篇章:關於 React Native 之 ListView 元件的講解

(友情提示:RN學習,從最基礎的開始,大家不要嫌棄太基礎,會的同學請自行略過,希望不要耽誤已經會的同學的寶貴時間)

我們講完ScrollView元件,其實順其自然的就應該講解ListView,對於前段和移動端的開發人員應該非常熟悉這樣的控制元件吧,具體是做什麼的,我感覺不用我講了吧。我們來看看它怎麼使用吧。

大家好,我是ListView,我是React Native大家族中基礎元件中,一個核心元件。我可以高效的展示垂直滾動的變化的資料列表,而且這個列表有一個特點就是結構和資料比較相似才可以哦。

我和ScrollView那傢伙不太相同,我更適於長列表資料,且元素個數可以增刪。和ScrollView不同的是,我並不立即渲染所有元素,而是優先渲染螢幕上可見的元素。怎麼樣?是不是感覺我更聰明?

我有兩個必須的屬性是dataSource和renderRow。dataSource是列表的資料來源,而renderRow則逐個解析資料來源中的資料,然後返回一個設定好格式的元件來渲染。舉個例子:我最基本的使用方式就是建立一個ListView.DataSource資料來源,然後給它傳遞一個普通的資料陣列,再使用資料來源來例項化一個ListView元件,並且定義它的renderRow回撥函式,這個函式會接受陣列中的每個資料作為引數,返回一個可渲染的元件(作為我的每一行)。

記住:rowHasChanged函式也是我的必需屬性。用於比較兩行資料是否是同一個資料來判斷某行資料是否變化了。

官方簡單例子

class MyComponent extends Component {
  constructor() {
    super();
    const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
      dataSource: ds.cloneWithRows(['row 1', 'row 2']),
    };
  }

  render() {
    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={(rowData) => <Text>{rowData}</Text>}
      />
    );
  }
}

高階屬性

想我這麼聰明的元件,我當然還支援一些高階的特性,比如:給每組陣列加一個粘節標題,也就是類似於通訊錄中其首字母會在滑動過程中吸附在螢幕上方,支援頁首和頁尾,也就是可以在列表中新增頭部和尾部。在到達列表尾部的時候呼叫回撥函式(onEndReached),還有在視野內可見的資料變化時呼叫回撥函式(onChangeVisibleRows),以及一些效能方面的優化。

在我母親制定的官方介紹中,這麼說:有一些效能優化使得我ListView可以滾動的更加平滑,尤其是在動態載入可能很大(或者概念上無限長的)資料集的時候:

  • 只更新變化的行 - 提供了rowHasChanged函式可以告訴ListView它是否需要重繪一行資料。
  • 限制頻率的行渲染 - 預設情況下,每次訊息迴圈只有一行會被渲染(可以用pageSize屬性配置)。這把較大的工作分散成小的碎片,以降低因為渲染而導致丟幀的可能性。

基本屬性

介紹完我的高階功能特性,再來看看我的基本屬性吧,懂了這些,你可以玩我跟玩孩子似的,運用自如。

我前面說了,我這人比ScrollView那傢伙聰明多了,所以它的屬性,我都能用,這裡關於和ScrollView相同的屬性就不贅述了。看看我的與眾不同,比它聰明在哪吧?

  • dataSource 傳入的資料來源
  • enableEmptySections bool 空內容的sections是否被渲染,預設是會渲染
  • initialListSize number 指定在元件剛掛載的時候渲染多少行資料。用這個屬性來確保首屏顯示合適數量的資料,而不是花費太多幀逐步顯示出來。
  • onChangeVisibleRows function 當可見的行發生變化的時候回撥該函式。visibleRows引數對所有可見的行為{selectionID:{rowId:true}}的形式,changedRow引數對已經改變可見的行為{selectionID:{rowID:true|false}}。該值true代表可見,false代表在檢視之外不可見的行。
  • onEndReached function 當所有的資料都已經渲染過,並且列表被滾動到距離最底部不足onEndReachedThreshold個畫素的距離時呼叫。原生的滾動事件會被作為引數傳遞。譯註:當第一次渲染時,如果資料不足一屏(比如初始值是空的),這個事件也會被觸發。
  • onEndReachedThreshold number 呼叫onEndReached之前的臨界值,單位是畫素。
  • pageSize number 每一次事件的迴圈渲染的行數。
  • removeClippedSubviews bool 用於提升大列表的滾動效能。需要給行容器新增樣式overflow:'hidden'。(Android已預設新增此樣式)。此屬性預設開啟。
  • renderFooter function 方法 ()=>renderable ,在每次渲染過程中頭和尾總會重新進行渲染。如果發現該重新繪製的效能開銷比較大的時候,可以使用StaticContainer容器或者其他合適的元件。在每一次渲染過程中Footer(尾)該會一直在列表的底部,header(頭)該會一直在列表的頭部
  • renderHeader function 與上同理
  • renderRow function (rowData, sectionID, rowID, highlightRow) => renderable 從資料來源(Data source)中接受一條資料,以及它和它所在section的ID。返回一個可渲染的元件來為這行資料進行渲染。預設情況下引數中的資料就是放進資料來源中的資料本身,不過也可以提供一些轉換器。如果某一行正在被高亮(通過呼叫highlightRow函式),ListView會得到相應的通知。當一行被高亮時,其兩側的分割線會被隱藏。行的高亮狀態可以通過呼叫highlightRow(null)來重置。
  • renderScrollComponent function 返回在列表行呈現的滾動元件的功能。預設為ScrollView。
  • renderSectionHeader function (sectionData, sectionID) => renderable 如果提供了此函式,會為每個小節(section)渲染一個粘性的標題。粘性是指當它剛出現時,會處在對應小節的內容頂部;繼續下滑當它到達螢幕頂端的時候,它會停留在螢幕頂端,一直到對應的位置被下一個小節的標題佔據為止。
  • renderSeparator function 如果提供了此屬性,一個可渲染的元件會被渲染在每一行下面,除了小節標題的前面的最後一行。在其上方的小節ID和行ID,以及鄰近的行是否被高亮會作為引數傳遞進來。
  • scrollRenderAheadDistance number 當該行進入螢幕多少畫素以內之後就開始渲染該行
  • stickyHeaderIndices [number] ios獨有 一個子檢視下標的陣列,用於決定哪些成員會在滾動之後固定在螢幕頂端。

例項演示

效果圖

來,看看我美不美,好不好用,我的真實面目如下:

程式碼

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  ListView,
  Image,
  TouchableHighlight,
  View
} from 'react-native';

class ListViewDemo extends Component {
  constructor(props) {
    super(props);
    const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
      dataSource: ds.cloneWithRows(this._genRows(-1))
    };
  }

  _genRows(flag){
        const dataBlob = [];
        for(let i = 0 ; i< 88 ; i ++ ){
          if(i == flag){
            dataBlob.push("非著名程式設計師+我被打了"+i);
          }else{
             dataBlob.push("非著名程式設計師"+i);
          }
        }
        return dataBlob;
    }

  render() {
    return (
        <ListView
          dataSource={this.state.dataSource}
          renderRow={this._renderRow.bind(this)}
        />

    );
  }

  _renderRow (rowData,sectionID, rowID) {
    return (
        <TouchableHighlight onPress={() => {
          this._pressRow(rowData,rowID);
        }}
        underlayColor='red'
        >
          <View>
            <View style={styles.row}>
              <Image style={{width:40,height:40}} source={require('./Thumbnails/head.jpg')}/>
              <Text style={{flex:1,fontSize:20,marginLeft:20}}>
                {rowData}
              </Text>
            </View>
          </View>
        </TouchableHighlight>
    );
   }

  _pressRow(rowData,rowID){
        alert(rowData);
        this.setState({dataSource: this.state.dataSource.cloneWithRows(
        this._genRows(rowID)
    )});
    }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  row: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems:'center',
    padding: 10,
  },
});

AppRegistry.registerComponent('ListViewDemo', () => ListViewDemo);

ok,關於ListView元件的講解大概就先講到這裡,更多的內容和例項,歡迎大家移步到官網,看文件,但是官網上大部分的例子用的是es5的語法。 官方文件地址:https://facebook.github.io/react-native/docs/listview.html