<button id="9slfp"><object id="9slfp"></object></button>
<button id="9slfp"><object id="9slfp"><menuitem id="9slfp"></menuitem></object></button>
    <em id="9slfp"></em>
    <button id="9slfp"><acronym id="9slfp"><input id="9slfp"></input></acronym></button>
  • 免費開源的iOS開發學習平臺

    React Native基礎:15-ListView組件

    ListView組件簡介

    ListView組件是一個可以在垂直方向滾動的列表組件。從本質來說,ListView組件是對ScrollView組件的定制,優化了組件對內存資源的使用效率,提高了性能。與ScrollView組件不同的是,ListView組件不會把所有元素都立刻渲染出來,其只會渲染屏幕內可見區域的元素,從而節省對硬件資源的消耗。

    一般來說,如果需要展示的數據量很大,并且每一行界面元素的結構相同或相似,推薦使用ListView組件來渲染界面。由于手機屏幕的尺寸都不大,因此使用React Native開發的移動應用,基本上都會用到ListView組件。

    ListView組件有兩個核心屬性:dataSource與renderRow,這兩個屬性必需設置。ListView組件通過dataSource屬性獲取需要顯示的數據,并且通過renderRow獲取數據展示的樣式。

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

    ListViewDataSource介紹

    ListViewDataSource類型的屬性dataSource為ListView組件提供高性能的數據處理和訪問。我們需要調用方法從原始輸入數據中抽取數據來創建ListViewDataSource對象,并用其進行數據變更的比較。原始輸入數據可以是簡單的字符串數組,也可以是復雜嵌套的對象——分不同區(section)各自包含若干行(row)數據。

    每次更新datasource中的數據,都需要重新調用cloneWithRows方法(如果用到了section,則對應cloneWithRowsAndSections方法)。數據源中的數據本身是不可修改的,所以請勿直接嘗試修改。clone方法會自動提取新數據并進行逐行對比(使用rowHasChanged方法中的策略),這樣ListView就知道哪些行需要重新渲染了。

    在下方的示例代碼中,先通過創建設置rowHasChanged屬性來創建一個ListView.DataSource實例。rowHasChanged是ListView.DataSource必需的屬性,通過這個屬性可以獲取哪些行的數據發生了變化,進而可以獲取到ListView中的哪些行需要重新渲染。ListView.DataSource的實例ds創建完成后,通過cloneWithRows方法來進行設置數據。cloneWithRows方法會自動提取新數據,并對比數據源檢查數據的變化,進而去刷新對應的行。如果dataSource中的數據發生了變化,需要重新調用cloneWithRows方法來設置它的數據。

    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    var dataSource = ds.cloneWithRows(this._genRows({}));
    

    在ListViewDataSource中,提供了一些用于對ListViewDataSource進行構建以及操作的方法,如下幾個比較常用。

    • constructor(params) :可以在此構造函數中針對section標題以及行數據提供自定義的提取方法和hasChanged比對方法。如果不提供,則會使用默認的defaultGetRowData和defaultGetSectionHeaderData方法來提取行數據和section標題。

    • cloneWithRows(dataBlob, rowIdentities) :根據指定的dataBlob和rowIdentities為ListViewDataSource復制填充數據。dataBlob即原始數據。需要在初始化時定義抽取函數,否則使用默認的抽取函數。rowIdentities是一個二維數組,包含了行數據對應的id標識符,例如[['a1', 'a2'], ['b1', 'b2', 'b3'], ...]。如果沒有指定此數組,則默認取行數據的key。

    • cloneWithRowsAndSections(dataBlob, sectionIdentities, rowIdentities) :此方法作用基本等同cloneWithRows,區別在于可以額外指定sectionIdentities 。sectionIdentities是包含了section標識符的數組,例如['s1', 's2', ...]。如果沒有指定此數組,則默認取section的key。

    • getRowData(sectionIndex, rowIndex) :返回渲染行所需的數據。

    • getSectionHeaderData(sectionIndex) :獲取section標題數據。

    示例代碼

    接下來我們實現一個ListView組件的例子,在ListView中會顯示100行數據,當用戶點擊某一行后會在標題上添加"(pressed)"提示。

    • 在終端中執行如下命令,創建ListViewDemo工程;
    react-native init ListViewDemo
    
    • 使用Atom打開工程的index.ios.js文件,編寫組件所使用的樣式
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        backgroundColor: '#F5FCFF',
        paddingTop: 20,
      },
      row: {
        flex: 1,
        margin: 10,
      },
    });
    
    • 創建ListView組件,設置其dataSouce和renderRow屬性,并實現用戶點擊每一行后更新顯示內容的功能。
    export default class ListViewDemo extends Component {
      _pressData = ({}: {[key: number]: boolean})
    
      constructor(props) {
        super(props);
    
        this._renderRow = this._renderRow.bind(this);
        this._pressRow = this._pressRow.bind(this);
    
        var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
        this.state = {
          dataSource: ds.cloneWithRows(this._genRows({})),
        };
      }
    
      render() {
        return (
          <View style={styles.container}>
            <ListView
              dataSource={this.state.dataSource}
              renderRow={this._renderRow}
              renderSeparator={this._renderSeparator}
            />
          </View>
        );
      }
    
      _renderRow(rowData: string, sectionID: number, rowID: number, highlightRow: (sectionID: number, rowID: number) => void) {
        return (
          <TouchableHighlight onPress={() => {
              console.log("this");
              console.log(this);
              this._pressRow(rowID);
              highlightRow(sectionID, rowID);
            }}>
            <View style={styles.row}>
              <Text>
                {rowData}
              </Text>
            </View>
          </TouchableHighlight>
        );
      }
    
      _pressRow(rowID: number) {
        this._pressData[rowID] = !this._pressData[rowID];
        this.setState({dataSource: this.state.dataSource.cloneWithRows(
          this._genRows(this._pressData)
        )});
      }
    
      _genRows(pressData: {[key: number]: boolean}): Array<string> {
        var dataBlob = [];
        for (var ii = 0; ii < 100; ii++) {
          var pressedText = pressData[ii] ? ' (pressed)' : '';
          dataBlob.push('Row ' + ii + pressedText);
        }
        return dataBlob;
      }
    }
    
    • 使用import加載項目所使用的模塊,并且注冊組件ListViewDemo成為整個應用的根容器。
    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      ListView,
      TouchableHighlight,
    } from 'react-native';
    
    AppRegistry.registerComponent('ListViewDemo', () => ListViewDemo);
    
    • 在終端中執行下面的命令運行程序,在iOS模擬器中可以看到展示的ListView組件,當我們點擊某一行時,改行的文字會發生改變。
    react-native run-ios
    


    精品h动漫无遮挡在线看中文|久久精品国产精品亚洲艾草|久久亚洲春色中文字幕|精品人妻少妇一区二区三区|欧美精品v国产精品v

    <button id="9slfp"><object id="9slfp"></object></button>
    <button id="9slfp"><object id="9slfp"><menuitem id="9slfp"></menuitem></object></button>
    <em id="9slfp"></em>
    <button id="9slfp"><acronym id="9slfp"><input id="9slfp"></input></acronym></button>