一、簡介
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' } });