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有):每次事件循环(每帧)渲染的行数,经常使用于分页,数据请求回来后渲染多少条,不设置则逐条渲染。

相关文章
相关标签/搜索