RN的ListView和SectionList

以下是對(duì)RN的ListView和SectionList學(xué)習(xí)的備忘錄:

ListView

對(duì)于ListView最重要的兩個(gè)屬性,一個(gè)是數(shù)據(jù)源(dataSource),再一個(gè)就是列表項(xiàng)渲染(renderRow)。ListView可以根據(jù)不同的數(shù)據(jù)結(jié)構(gòu)對(duì)應(yīng)的生成普通長(zhǎng)列表和分組長(zhǎng)列表。

普通長(zhǎng)列表

普通長(zhǎng)列表使用cloneWithRows(dataBlob, rowIdentities)創(chuàng)建datasource,在項(xiàng)目中dataBlob的數(shù)據(jù)結(jié)構(gòu)如下:

[

? ? {id:1},

? ? {name:'Mark'},

? ? ...

]

在使用renderRow(rowData, sectionID, rowID, highlightRow)渲染列表項(xiàng)的時(shí)候,rowData就是數(shù)組中每一個(gè)對(duì)象。

分組長(zhǎng)列表

在項(xiàng)目中,遇到分組長(zhǎng)列表,由于RN版本為0.44,所以有ListView和SectionList兩種選擇方案,最終我選擇了SectionList,因?yàn)槲野l(fā)現(xiàn)ListView的section只能是一個(gè)簡(jiǎn)單的字符串,不能是一個(gè)對(duì)象(這里說實(shí)話我也不知道對(duì)不對(duì),若不對(duì),請(qǐng)指正并說明如何使用ListView實(shí)現(xiàn)section是一個(gè)對(duì)象)。

這里我要吐槽一下RN的文檔,真的是有些地方寫的太簡(jiǎn)單,比如在ListView這里寫到使用cloneWithRowsAndSections的使用,只是簡(jiǎn)單的說跟cloneWithRows差不多,而接受的數(shù)據(jù)結(jié)構(gòu)也就簡(jiǎn)單的說明有三種:

{ sectionID_1: { rowID_1: <rowData1>, ... }, ... }

//or

{ sectionID_1: [ <rowData1>, <rowData2>, ... ], ... }

//or

[ [ <rowData1>, <rowData2>, ... ], ... ]

但是具體這里的是些什么,我覺得沒有說清楚。所以我在項(xiàng)目中試了下用ListView的cloneWithRowsAndSections實(shí)現(xiàn)帶有粘性標(biāo)題的列表,發(fā)現(xiàn)前兩種sectionID只能是一個(gè)簡(jiǎn)單的字符串或者數(shù)字,不能是一個(gè)對(duì)象,數(shù)據(jù)結(jié)構(gòu)如下:

const dataSource1 = [

? ? ['row1','row2'],

? ? ['row3','row4'],

? ? ['row5','row6'],

];

const dataSoure2 = {

? ? 'id1':['row1','row2'],

? ? 'id2':['row3','row4'],

? ? 'id3':['row5','row6'],

}

const dataSoure3 = {

? ? 'id1':{'row1','row2'},

? ? 'id2':{'row3','row4'},

? ? 'id3':{'row5','row6'},

}

cloneWithRowsAndSections(dataSource);

dataSoure1生成的sectionHeader是數(shù)組的下標(biāo),而第二個(gè)第三個(gè)分別是對(duì)應(yīng)的key,在項(xiàng)目中我的sectionHeader是一個(gè)對(duì)象,類似于{headerName:'',headerContent:''},所以無法使用。

SectionList分組長(zhǎng)列表

SectionList和FlatList一樣是新增的高性能長(zhǎng)列表,在文檔中關(guān)于SectionList接受的數(shù)據(jù)結(jié)構(gòu)描述如下:

<SectionList

? renderItem={({item}) => <ListItem title={item.title} />}

? renderSectionHeader={({section}) => <H1 title={section.title} />}

? sections={[ // homogenous rendering between sections

? ? {data: [...], title: ...},

? ? {data: [...], title: ...},

? ? {data: [...], title: ...},

? ]}

/>

<SectionList

? sections={[ // heterogeneous rendering between sections

? ? {data: [...], title: ..., renderItem: ...},

? ? {data: [...], title: ..., renderItem: ...},

? ? {data: [...], title: ..., renderItem: ...},

? ]}

/>

說實(shí)話我第一次看到這個(gè)描述的時(shí)候很懵逼,這好像并沒說明data里具體的數(shù)據(jù)結(jié)構(gòu)是什么樣子的,renderSectionHeader中的數(shù)據(jù)又該如何取,在網(wǎng)上看了一個(gè)簡(jiǎn)單的講解才大概知道sections里的數(shù)據(jù)應(yīng)該怎么寫,代碼如下:

import React , {Component} from 'react';

import {

? ? AppRegistry,

? ? StyleSheet,

? ? Text,

? ? View,

? ? SectionList

} from 'react-native';

const dataSource = [

? ? {data:[{name:'nader'},{name:'chris'}],key:'A'},

? ? {data:[{name:'nick'},{name:'amanda'}],key:'B'}

];

export default class SectionListExample extends Component {

? ? renderItem = (item) => {

? ? ? ? return <Text style={styles.text}>{item.item.name}</Text>

? ? }

? ? renderHeader = (headerItem) => {

? ? ? ? return <Text style={styles.header}>{headerItem.section.key}</Text>

? ? }

? ? render(){

? ? ? ? return(

? ? ? ? ? ? <View style={styles.container}>

? ? ? ? ? ? ? ? <SectionList

? ? ? ? ? ? ? ? ? ? renderItem={this.renderItem}

? ? ? ? ? ? ? ? ? ? renderSectionHeader={this.renderHeader}

? ? ? ? ? ? ? ? ? ? sections={dataSource}

? ? ? ? ? ? ? ? ? ? keyExtractor={(item)=>item.name}

? ? ? ? ? ? ? ? />

? ? ? ? ? ? </View>

? ? ? ? )

? ? }

}

這里需要注意一點(diǎn)就是renderItem所用的數(shù)據(jù)key必須是data,而且key必須是唯一的,然后其余的數(shù)據(jù)用在headerItem中,這樣就非常容易在sectionHeader中渲染出多個(gè)后臺(tái)給定的數(shù)據(jù)。

SectionList和FlatList需要注意幾點(diǎn):

文檔中提到為了優(yōu)化內(nèi)存占用同時(shí)保持滑動(dòng)的流暢,列表內(nèi)容會(huì)在屏幕外異步繪制。這意味著如果用戶滑動(dòng)的速度超過渲染的速度,則會(huì)先看到空白的內(nèi)容。這是為了優(yōu)化不得不作出的妥協(xié),而我們也在設(shè)法持續(xù)改進(jìn)。所以如果不想在滑動(dòng)過快導(dǎo)致白屏出現(xiàn),就只能使用ListView。

在我的項(xiàng)目中設(shè)置stickySectionHeadersEnabled={true}的時(shí)候,粘性標(biāo)題在往下滑動(dòng)一會(huì)兒再滑動(dòng)回去的時(shí)候,標(biāo)題會(huì)消失,這不知道是我代碼有問題還是本身SectionList的粘性標(biāo)題在安卓下就有問題,不過在官方文檔中寫到Only enabled by default on iOS because that is the platform standard there.所以可能是SectionList粘性標(biāo)題在安卓下就有問題。

SectionList和FlatList提供了一個(gè)叫l(wèi)egacyImplementation的屬性,該屬性如果設(shè)置為true則使用舊的ListView實(shí)現(xiàn)。在上述提到的兩個(gè)問題中,如果將SectionList的legacyImplementation設(shè)置為true,則兩個(gè)問題均解決。個(gè)人覺得這是官方提供的一個(gè)降級(jí)的辦法,所以其實(shí)我們可以拋棄ListView轉(zhuǎn)而使用FlatList和SectionList,如果有什么問題,讓它們用舊的ListView實(shí)現(xiàn)。

最后

最后列幾個(gè)長(zhǎng)列表(ListView,SectionList,F(xiàn)latList)的常用屬性

onEndReached(function):當(dāng)列表到達(dá)底部時(shí)候觸發(fā)的事件,關(guān)于這個(gè)事件需要注意一點(diǎn),當(dāng)?shù)谝淮武秩緯r(shí),如果數(shù)據(jù)不足一屏(比如初始值是空的),這個(gè)事件也會(huì)被觸發(fā),需要自行過濾

onEndReachedThreshold(number):距離最后一個(gè)列表元素多少像素時(shí)候觸發(fā)onEndReached事件

initialListSize(number):初始化時(shí)候渲染多少條數(shù)據(jù),如果不寫擇時(shí)逐條渲染

showsVerticalScrollIndicator(bool):默認(rèn)情況下,ListView有滾動(dòng)條,當(dāng)設(shè)置為false的時(shí)候不顯示該滾動(dòng)條(繼承自ScrollView)

pageSize(number,僅ListView有):每次事件循環(huán)(每幀)渲染的行數(shù),常用于分頁,數(shù)據(jù)請(qǐng)求回來后渲染多少條,不設(shè)置則逐條渲染。

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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