基礎篇章:關於 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