ReactNative學(xué)習(xí)筆記十一之FlatList

之前使用的組件是ListView,當(dāng)時(shí)要添加一個(gè)下拉刷新,上拉加載的功能,所以對(duì)ListView做了一些封裝,但是后來(lái)看官方文檔,不建議再使用ListView,因?yàn)樾蕟?wèn)題,做過(guò)Android的朋友都知道,Android的ListView如果不自己處理一下,也是有效率問(wèn)題的。所以官方又推出了FlatList,而且自帶上拉下拉的功能。


功能簡(jiǎn)介

  • 完全跨平臺(tái)。
  • 支持水平布局模式。
  • 行組件顯示或隱藏時(shí)可配置回調(diào)事件。
  • 支持單獨(dú)的頭部組件。
  • 支持單獨(dú)的尾部組件。
  • 支持自定義行間分隔線。
  • 支持下拉刷新。
  • 支持上拉加載。
  • 支持跳轉(zhuǎn)到指定行(ScrollToIndex)。
    如果需要分組/類/區(qū)(section),請(qǐng)使用SectionList(這個(gè)我們會(huì)在之后的文章中介紹)

使用

FlatList如果只做簡(jiǎn)單使用也是很簡(jiǎn)單的,這里我們會(huì)分難以程度,逐漸介紹:

直接使用

<FlatList
  data={[{key: 'a'}, {key: 'b'}]}
  renderItem={({item}) => <Text>{item.key}</Text>}
/>

可以看出跟之前的ListView很像,但是其中少了dataSource,這里,我們只需要傳遞數(shù)據(jù),其它的都交給FlatList處理好了。

屬性說(shuō)明

  • ItemSeparatorComponent
    行與行之間的分隔線組件。不會(huì)出現(xiàn)在第一行之前和最后一行之后。?在這里可以根據(jù)需要插入一個(gè)view

  • ListEmptyComponent
    列表為空時(shí)渲染該組件??梢允荝eact Component, 也可以是一個(gè)render函數(shù), 或者渲染好的element。

  • ListFooterComponent
    尾部組件

  • ListHeaderComponent
    頭部組件

  • columnWrapperStyle
    如果設(shè)置了多列布局(即將numColumns
    值設(shè)為大于1的整數(shù)),則可以額外指定此樣式作用在每行容器上。

  • data
    為了簡(jiǎn)化起見(jiàn),data屬性目前只支持普通數(shù)組。如果需要使用其他特殊數(shù)據(jù)結(jié)構(gòu),例如immutable數(shù)組,請(qǐng)直接使用更底層的VirtualizedList
    組件。

  • extraData
    如果有除data以外的數(shù)據(jù)用在列表中(不論是用在renderItem
    還是Header或者Footer中),請(qǐng)?jiān)诖藢傩灾兄付āM瑫r(shí)此數(shù)據(jù)在修改時(shí)也需要先修改其引用地址(比如先復(fù)制到一個(gè)新的Object或者數(shù)組中),然后再修改其值,否則界面很可能不會(huì)刷新。

  • getItem
    獲取每個(gè)Item

  • getItemCount
    獲取Item屬相

  • getItemLayout
    是一個(gè)可選的優(yōu)化,用于避免動(dòng)態(tài)測(cè)量?jī)?nèi)容尺寸的開(kāi)銷,不過(guò)前提是你可以提前知道內(nèi)容的高度。如果你的行高是固定的getItemLayout
    用起來(lái)就既高效又簡(jiǎn)單,類似下面這樣:
    getItemLayout={(data, index) => ( {length: 行高, offset: 行高 * index, index} )}注意如果你指定了SeparatorComponent,請(qǐng)把分隔線的尺寸也考慮到offset的計(jì)算之中。

  • horizontal
    設(shè)置為true則變?yōu)樗讲季帜J健?/p>

  • initialNumToRender
    指定一開(kāi)始渲染的元素?cái)?shù)量,最好剛剛夠填滿一個(gè)屏幕,這樣保證了用最短的時(shí)間給用戶呈現(xiàn)可見(jiàn)的內(nèi)容。注意這第一批次渲染的元素不會(huì)在滑動(dòng)過(guò)程中被卸載,這樣是為了保證用戶執(zhí)行返回頂部的操作時(shí),不需要重新渲染首批元素。

  • initialScrollIndex
    指定渲染開(kāi)始的item index

  • keyExtractor
    此函數(shù)用于為給定的item生成一個(gè)不重復(fù)的key。Key的作用是使React能夠區(qū)分同類元素的不同個(gè)體,以便在刷新時(shí)能夠確定其變化的位置,減少重新渲染的開(kāi)銷。若不指定此函數(shù),則默認(rèn)抽取item.key作為key值。若item.key也不存在,則使用數(shù)組下標(biāo)。

  • legacyImplementation
    設(shè)置為true則使用舊的ListView的實(shí)現(xiàn)。

  • numColumns
    多列布局只能在非水平模式下使用,即必須是horizontal={false}
    。此時(shí)組件內(nèi)元素會(huì)從左到右從上到下按Z字形排列,類似啟用了flexWrap的布局。組件內(nèi)元素必須是等高的——暫時(shí)還無(wú)法支持瀑布流布局。

  • onEndReached
    當(dāng)列表被滾動(dòng)到距離內(nèi)容最底部不足onEndReachedThreshold
    的距離時(shí)調(diào)用。

  • onEndReachedThreshold
    決定當(dāng)距離內(nèi)容最底部還有多遠(yuǎn)時(shí)觸發(fā)onEndReached
    回調(diào)。注意此參數(shù)是一個(gè)比值而非像素單位。比如,0.5表示距離內(nèi)容最底部的距離為當(dāng)前列表可見(jiàn)長(zhǎng)度的一半時(shí)觸發(fā)。

  • onRefresh
    如果設(shè)置了此選項(xiàng),則會(huì)在列表頭部添加一個(gè)標(biāo)準(zhǔn)的RefreshControl
    控件,以便實(shí)現(xiàn)“下拉刷新”的功能。同時(shí)你需要正確設(shè)置refreshing
    屬性。

  • onViewableItemsChanged
    在可見(jiàn)行元素變化時(shí)調(diào)用。可見(jiàn)范圍和變化頻率等參數(shù)的配置請(qǐng)?jiān)O(shè)置viewabilityconfig屬性

  • refreshing
    在等待加載新數(shù)據(jù)時(shí)將此屬性設(shè)為true,列表就會(huì)顯示出一個(gè)正在加載的符號(hào)。

  • renderItem
    根據(jù)行數(shù)據(jù)data,渲染每一行的組件。這個(gè)參照下面的demo

  • viewabilityConfig
    請(qǐng)參考ViewabilityHelper
    的源碼來(lái)了解具體的配置。

方法

  • scrollToEnd
    滾動(dòng)到底部。如果不設(shè)置getItemLayout
    屬性的話,可能會(huì)比較卡。

  • scrollToIndex
    滾動(dòng)到指定index的item
    如果不設(shè)置getItemLayout
    屬性的話,無(wú)法跳轉(zhuǎn)到當(dāng)前可視區(qū)域以外的位置。

  • scrollToItem
    滾動(dòng)到指定item,如果不設(shè)置getItemLayout
    屬性的話,可能會(huì)比較卡。

  • scrollToOffset
    滾動(dòng)指定距離

進(jìn)階使用

在這里我準(zhǔn)備了一份代碼示例:


const {width,height}=Dimensions.get('window')
export default class Main extends Component{
    // 構(gòu)造
    constructor(props) {
        super(props);
    }
    refreshing(){
        let timer =  setTimeout(()=>{
                    clearTimeout(timer)
                    alert('刷新成功')
                },1500)
    }
    _onload(){
        let timer =  setTimeout(()=>{
            clearTimeout(timer)
            alert('加載成功')
        },1500)
    }
    render() {
        var data = [];
        for (var i = 0; i < 100; i++) {
            data.push({key: i, title: i + ''});
        }

        return (
            <View style={{flex:1}}>
                <Button title='滾動(dòng)到指定位置' onPress={()=>{
                    this._flatList.scrollToOffset({animated: true, offset: 2000});
                }}/>
                <View style={{flex:1}}>
                    <FlatList
                        ref={(flatList)=>this._flatList = flatList}
                        ListHeaderComponent={this._header}
                        ListFooterComponent={this._footer}
                        ItemSeparatorComponent={this._separator}
                        renderItem={this._renderItem}
                        onRefresh={this.refreshing}
                        refreshing={false}
                        onEndReachedThreshold={0}
                        onEndReached={
                            this._onload
                        }
                        numColumns ={3}
                        columnWrapperStyle={{borderWidth:2,borderColor:'black',paddingLeft:20}}

                        //horizontal={true}

                        getItemLayout={(data,index)=>(
                        {length: 100, offset: (100+2) * index, index}
                        )}

                        data={data}>
                    </FlatList>
                </View>

            </View>
        );
    }


    _renderItem = (item) => {
        var txt = '第' + item.index + '個(gè)' + ' title=' + item.item.title;
        var bgColor = item.index % 2 == 0 ? 'red' : 'blue';
        return <Text style={[{flex:1,height:100,backgroundColor:bgColor},styles.txt]}>{txt}</Text>
    }

    _header = () => {
        return <Text style={[styles.txt,{backgroundColor:'black'}]}>這是頭部</Text>;
    }

    _footer = () => {
        return <Text style={[styles.txt,{backgroundColor:'black'}]}>這是尾部</Text>;
    }

    _separator = () => {
        return <View style={{height:2,backgroundColor:'yellow'}}/>;
    }


}
const styles=StyleSheet.create({
    container:{

    },
    content:{
        width:width,
        height:height,
        backgroundColor:'yellow',
        justifyContent:'center',
        alignItems:'center'
    },
    cell:{
        height:100,
        backgroundColor:'purple',
        alignItems:'center',
        justifyContent:'center',
        borderBottomColor:'#ececec',
        borderBottomWidth:1

    },
    txt: {
        textAlign: 'center',
        textAlignVertical: 'center',
        color: 'white',
        fontSize: 30,
    }

})

運(yùn)行效果如下:

總結(jié)

總體來(lái)說(shuō)Flatlist還是比ListView用起來(lái)方便的,而且提供的功能更多。


之前文章合集:
Android文章合集
iOS文章合集
ReactNative文章合集
如果你也做ReactNative開(kāi)發(fā),并對(duì)ReactNative感興趣,歡迎關(guān)注我的公眾號(hào),加入我們的討論群:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容