免費開源的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
                                                


                                                欧美超级精品一级A片|欧美一级黄色视频|国产精品自在在线午夜免费|4444亚洲人成无码网在线观看|亚洲ⅴa曰本va欧美va视频