一、簡介
SectionList,分組列表,ReactNative中繼提供的ListView和FlatList列表組件后的又一個很重要的分組列表組件。它的用法其實跟前面的FlatList差不多,但是SectionList組件性能更高,同時SectionList組件要比ListView組件使用簡單的多。SectionList組件的功能非常強大,如下所示。現在我們來仔細研究一下這個組件的API。
- 完全跨平台。
- 可配置的可見性回調。
- 列表標題支持。
- 列出頁腳支持。
- 項目分隔符支持。
- 節標題支持。
- 部分分隔符支持。
- 異構數據和項目渲染支持。
- 拉動以刷新。
- 滾動加載。
二、API
SectionList組件同樣地對屬性是必須直接提供的,有些是可選的。如下所示:
//分組基類SectionBase對象結構, 泛型為SectionItemT type SectionBase<SectionItemT> = { //數據源數組,必需屬性 data: Array<SectionItemT>, //每一組數據源的標識符 ,必需屬性 key: string,
//每一組的每一個item組件,可選屬性 renderItem?: ?(info: {item: SectionItemT, index: number}) => ?React.Element<any>, //分割線,可選屬性 ItemSeparatorComponent?: ?ReactClass<any>, //標識符,可選屬性 keyExtractor?: (item: SectionItemT) => string, }; //必要的屬性 //sections,是一個泛型數組,類型為SectionT,存儲的是SectionBase對象 type RequiredProps<SectionT: SectionBase<any>> = { sections: Array<SectionT>, }; //可選的屬性 type OptionalProps<SectionT: SectionBase<any>> = { //每個部分中每個項目的默認渲染器。 可以逐段覆蓋。 renderItem: (info: {item: Item, index: number}) => ?React.Element<any>, //在每個部分的相鄰項目之間渲染。每一個item的分割線 ItemSeparatorComponent?: ?ReactClass<any>, //在列表的最開始呈現。表頭 ListHeaderComponent?: ?ReactClass<any>, //呈現在列表的最后。表尾 ListFooterComponent?: ?ReactClass<any>, //在每個部分之間渲染。組分割線 SectionSeparatorComponent?: ?ReactClass<any>, //一個標記屬性,用於告訴列表重新渲染(因為它實現了`PureComponent`)。
//如果您的`renderItem`,Header,Footer等函數中的任何一個都依賴於`data`道具之外的任何東西,請將其粘貼在這里並一視同仁。 extraData?: any, //頁面初次渲染的個數,可以不用等所有頁面渲染出來再顯示UI initialNumToRender: number, //用於提取指定索引處給定項目的唯一鍵。 鍵用於緩存,並用作反應鍵以跟蹤項的重新排序。 默認的提取器檢查item.key,然后像react一樣退回到使用索引。 keyExtractor: (item: Item, index: number) => string, //滾動位置在渲染內容的onEndReachedThreshold范圍內時調用一次。 onEndReached?: ?(info: {distanceFromEnd: number}) => void, //列表的底邊必須從內容的末尾到末尾(以列表的可見長度為單位)多遠,才能觸發onEndReached回調。
//因此,當內容的結尾在列表的可見長度的一半以內時,值為0.5將觸發“ onEndReached”。 onEndReachedThreshold?: ?number, //如果提供,將為“拉動刷新”功能添加標准的RefreshControl。 onRefresh?: ?() => void, //當行的可視性發生變化時調用,如`viewabilityConfig`屬性所定義。 onViewableItemsChanged?: ?(info: { viewableItems: Array<ViewToken>, changed: Array<ViewToken>, }) => void, //等待刷新之前的新數據時,將其設置為true。 refreshing?: ?boolean, //呈現在每個部分的頂部。 尚不支持粘性標頭。組頭 renderSectionHeader?: ?(info: {section: SectionT}) => ?React.Element<any>, //使節標題停留在屏幕頂部,直到下一個將其關閉。 僅在iOS上默認啟用,因為這是該平台的平台標准。 stickySectionHeadersEnabled?: boolean, };
三、使用
看完API,可以發現接收的數據數組sections存儲的都是SectionBase,而每一個SectionBase內部都必需包含data數組和key唯一標識,剩余的元素是可選的。其實挺簡單的,現在來實現一下部分功能,示例如下:
MySectionListView.js
import React, { Component } from 'react';
import {
StyleSheet,
View,
Image,
Text,
Dimensions,
SectionList
} from 'react-native';
const {width} = Dimensions.get('window');
const itemPadding = 20;
const itemWidth = (width-4*itemPadding)/3;
console.log('width:'+width);
const fetch_data = [
{
"type":"A",
"flowers":[
{
icon:require('../image/flower1.png'),
title:'玫瑰'
},
{
icon:require('../image/flower1.png'),
title:'玫瑰'
},
{
icon:require('../image/flower1.png'),
title:'玫瑰'
}
]
},
{
"type":"B",
"flowers":[
{
icon:require('../image/flower2.png'),
title:'草芽'
},
{
icon:require('../image/flower2.png'),
title:'草芽'
},
{
icon:require('../image/flower2.png'),
title:'草芽'
}
]
},
{
"type":"C",
"flowers":[
{
icon:require('../image/flower3.png'),
title:'向日葵'
},
{
icon:require('../image/flower3.png'),
title:'向日葵'
},
{
icon:require('../image/flower3.png'),
title:'向日葵'
}
]
},
{
"type":"D",
"flowers":[
{
icon:require('../image/flower4.png'),
title:'月季'
},
{
icon:require('../image/flower4.png'),
title:'月季'
},
{
icon:require('../image/flower4.png'),
title:'月季'
}
]
}
];
export default class MySectionListView extends Component{
//渲染item info: {item: Item, index: number}
_renderItem(info){
return (
<View style={styles.item}>
<Image style={styles.image} source={info.item.icon}/>
<Text style={styles.text}>{info.item.title}</Text>
</View>
)
}
//渲染組頭 info: {section: SectionT}
_renderSectionHeader(info){
return (
<View style={styles.sectionHeader}>
<Text key={info.section.key}
style={{color:'white',fontSize: 25,justifyContent: 'center'}}>
{info.section.type}
</Text>
</View>
)
}
//渲染表頭
_listHeaderComponent(){
return (
<View style={{width:width,height:200,backgroundColor:'red'}}/>
)
}
//渲染表尾
_listFooterComponent(){
return (
<View style={{width:width,height:200,backgroundColor:'green'}}/>
)
}
render() {
//sections數據源
let sections = [];
for (let i = 0; i < fetch_data.length; i++) {
//創建SectionBase對象,初始化key唯一標識,和data數組
let data = [];
const type = fetch_data[i].type;
const flowers = fetch_data[i].flowers;
for(let j=0; j<flowers.length; j++){
data.push(flowers[j]);
}
sections.push({key: i, data: data, type:type});
}
return (
<View style={styles.flex}>
<SectionList
sections={sections}
renderItem={this._renderItem}
keyExtractor={(item, index) => ("index:" + index + item)}
contentContainerStyle={styles.section}
renderSectionHeader={this._renderSectionHeader}
ListHeaderComponent={this._listHeaderComponent}
ListFooterComponent={this._listFooterComponent}
/>
</View>
);
}
}
const styles = StyleSheet.create({
flex: {
flex: 1,
},
center: {
alignItems: 'center',
justifyContent: 'center'
},
section: {
flexDirection: 'row',
flexWrap: 'wrap',
backgroundColor:'#EEE'
},
item: {
width: itemWidth,
marginTop: 10,
marginBottom: 10,
marginLeft: itemPadding,
justifyContent: 'center',
backgroundColor: '#21c6cd'
},
image: {
width: itemWidth,
height: 150
},
text: {
marginTop: 5,
width: itemWidth,
fontSize: 25,
textAlign: 'center'
},
sectionHeader: {
height: 30,
width: width,
backgroundColor: 'gray'
}
});
