RN長列表--ListView && SectionList

忽然發現本身的博客已經從原來的幾天更新一次變成了現在的一個月更新一次[捂臉],最近這一個月實在是太忙了,上個月月初的時候,接了一個RN的項目,作一個app,那時候老大問誰感興趣,我直接說我。其實本身對RN一直頗有興趣,可是那時候因爲在看Vue,因此並無去搞,如今恰好有個項目,正好我能夠去了解一下RN。說實話,這一答應沒關係,差點兒被RN氣死,之前以爲RN應該比較成熟了,通過這段時間作項目,發現RN的坑仍是不少的。react

在項目中我用到的比較多的是長列表,因此這篇文章主要是記一下對RN的ListViewSectionList的一些總結。我項目中使用的RN是0.44,關於爲何不用性能更好的FlatList而使用老的ListView,是由於本身自己第一次接觸RN,因此擔憂用很差FlatList並且擔憂會有什麼bug,畢竟這個是在0.43版本才添加的。react-native

ListView

對於ListView最重要的兩個屬性,一個是數據源(dataSource),再一個就是列表項渲染(renderRow)。ListView能夠根據不一樣的數據結構對應的生成普通長列表和分組長列表。數組

普通長列表

普通長列表使用cloneWithRows(dataBlob, rowIdentities)建立datasource,在項目中dataBlob的數據結構以下:數據結構

[
    {id:1},
    {name:'Mark'},
    ...
]

在使用renderRow(rowData, sectionID, rowID, highlightRow)渲染列表項的時候,rowData就是數組中每個對象。app

分組長列表

在項目中,遇到分組長列表,因爲RN版本爲0.44,因此有ListViewSectionList兩種選擇方案,最終我選擇了SectionList,由於我發現ListViewsection只能是一個簡單的字符串,不能是一個對象(這裏說實話我也不知道對不對,若不對,請指正並說明如何使用ListView實現section是一個對象)。異步

這裏我要吐槽一下RN的文檔,真的是有些地方寫的太簡單,好比在ListView這裏寫到使用cloneWithRowsAndSections的使用,只是簡單的說跟cloneWithRows差很少,而接受的數據結構也就簡單的說明有三種:性能

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

可是具體這裏的是些什麼,我以爲沒有說清楚。因此我在項目中試了下用ListViewcloneWithRowsAndSections實現帶有粘性標題的列表,發現前兩種sectionID只能是一個簡單的字符串或者數字,不能是一個對象,數據結構以下:優化

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是數組的下標,而第二個第三個分別是對應的key,在項目中個人sectionHeader是一個對象,相似於{headerName:'',headerContent:''},因此沒法使用。this

SectionList分組長列表

SectionListFlatList同樣是新增的高性能長列表,在文檔中關於SectionList接受的數據結構描述以下:spa

<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: ...},
  ]}
/>

說實話我第一次看到這個描述的時候很懵逼,這好像並沒說明data裏具體的數據結構是什麼樣子的,renderSectionHeader中的數據又該如何取,在網上看了一個簡單的講解才大概知道sections裏的數據應該怎麼寫,代碼以下:

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

這裏須要注意一點就是renderItem所用的數據key必須是data,並且key必須是惟一的,而後其他的數據用在headerItem中,這樣就很是容易在sectionHeader中渲染出多個後臺給定的數據。

SectionListFlatList須要注意幾點:

  • 文檔中提到<span style='color:red'>爲了優化內存佔用同時保持滑動的流暢,列表內容會在屏幕外異步繪製。這意味着若是用戶滑動的速度超過渲染的速度,則會先看到空白的內容。這是爲了優化不得不做出的妥協,而咱們也在設法持續改進。</span>因此若是不想在滑動過快致使白屏出現,就只能使用ListView
  • 在個人項目中設置stickySectionHeadersEnabled={true}的時候,粘性標題在往下滑動一下子再滑動回去的時候,標題會消失,這不知道是我代碼有問題仍是自己SectionList的粘性標題在安卓下就有問題,不過在官方文檔中寫到Only enabled by default on iOS because that is the platform standard there.因此多是SectionList粘性標題在安卓下就有問題。
  • SectionListFlatList提供了一個叫legacyImplementation的屬性,該屬性若是設置爲true則使用舊的ListView實現。在上述提到的兩個問題中,若是將SectionListlegacyImplementation設置爲true,則兩個問題均解決。我的以爲這是官方提供的一個降級的辦法,因此其實咱們能夠拋棄ListView轉而使用FlatListSectionList,若是有什麼問題,讓它們用舊的ListView實現。

最後

最後列幾個長列表(ListViewSectionListFlatList)的經常使用屬性

onEndReached(function):當列表到達底部時候觸發的事件,關於這個事件須要注意一點,<span style='color:red'>當第一次渲染時,若是數據不足一屏(好比初始值是空的),這個事件也會被觸發,須要自行過濾</span>

onEndReachedThreshold(number):距離最後一個列表元素多少像素時候觸發onEndReached事件

initialListSize(number):初始化時候渲染多少條數據,若是不寫擇時逐條渲染

showsVerticalScrollIndicator(bool):默認狀況下,ListView有滾動條,當設置爲false的時候不顯示該滾動條(繼承自ScrollView)

pageSize(number,僅ListView有):每次事件循環(每幀)渲染的行數,經常使用於分頁,數據請求回來後渲染多少條,不設置則逐條渲染。

相關文章
相關標籤/搜索