ReactNative: 使用分組列表組件SectionList組件


一、簡介

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'
   }
});

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM