基礎篇章:關于 React Native 之 ListView 組件的講解
我們講完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的語法。
來自:http://godcoder.me/2016/11/02/基礎篇章:關于 React Native 之 ListView 組件的講解/