忽然发现本身的博客已经从原来的几天更新一次变成了现在的一个月更新一次[捂脸],最近这一个月实在是太忙了,上个月月初的时候,接了一个RN的项目,作一个app,那时候老大问谁感兴趣,我直接说我。其实本身对RN一直颇有兴趣,可是那时候因为在看Vue,因此并无去搞,如今恰好有个项目,正好我能够去了解一下RN。说实话,这一答应没关系,差点儿被RN气死,之前以为RN应该比较成熟了,通过这段时间作项目,发现RN的坑仍是不少的。react
在项目中我用到的比较多的是长列表,因此这篇文章主要是记一下对RN的ListView
和SectionList
的一些总结。我项目中使用的RN是0.44,关于为何不用性能更好的FlatList
而使用老的ListView
,是由于本身自己第一次接触RN,因此担忧用很差FlatList
并且担忧会有什么bug,毕竟这个是在0.43版本才添加的。react-native
对于ListView
最重要的两个属性,一个是数据源(dataSource),再一个就是列表项渲染(renderRow)。ListView
能够根据不一样的数据结构对应的生成普通长列表和分组长列表。数组
普通长列表使用cloneWithRows(dataBlob, rowIdentities)
建立datasource,在项目中dataBlob
的数据结构以下:数据结构
[ {id:1}, {name:'Mark'}, ... ]
在使用renderRow(rowData, sectionID, rowID, highlightRow)
渲染列表项的时候,rowData
就是数组中每个对象。app
在项目中,遇到分组长列表,因为RN版本为0.44,因此有ListView
和SectionList
两种选择方案,最终我选择了SectionList
,由于我发现ListView
的section
只能是一个简单的字符串,不能是一个对象(这里说实话我也不知道对不对,若不对,请指正并说明如何使用ListView
实现section
是一个对象)。异步
这里我要吐槽一下RN的文档,真的是有些地方写的太简单,好比在ListView
这里写到使用cloneWithRowsAndSections
的使用,只是简单的说跟cloneWithRows
差很少,而接受的数据结构也就简单的说明有三种:性能
{ sectionID_1: { rowID_1: <rowData1>, ... }, ... } //or { sectionID_1: [ <rowData1>, <rowData2>, ... ], ... } //or [ [ <rowData1>, <rowData2>, ... ], ... ]
可是具体这里的是些什么,我以为没有说清楚。因此我在项目中试了下用ListView
的cloneWithRowsAndSections
实现带有粘性标题的列表,发现前两种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
和FlatList
同样是新增的高性能长列表,在文档中关于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
中渲染出多个后台给定的数据。
SectionList
和FlatList
须要注意几点:ListView
。stickySectionHeadersEnabled={true}
的时候,粘性标题在往下滑动一下子再滑动回去的时候,标题会消失,这不知道是我代码有问题仍是自己SectionList
的粘性标题在安卓下就有问题,不过在官方文档中写到Only enabled by default on iOS because that is the platform standard there.
因此多是SectionList
粘性标题在安卓下就有问题。SectionList
和FlatList
提供了一个叫legacyImplementation
的属性,该属性若是设置为true
则使用旧的ListView
实现。在上述提到的两个问题中,若是将SectionList
的legacyImplementation
设置为true
,则两个问题均解决。我的以为这是官方提供的一个降级的办法,因此其实咱们能够抛弃ListView
转而使用FlatList
和SectionList
,若是有什么问题,让它们用旧的ListView
实现。最后列几个长列表(ListView
,SectionList
,FlatList
)的经常使用属性
onEndReached
(function):当列表到达底部时候触发的事件,关于这个事件须要注意一点,<span style='color:red'>当第一次渲染时,若是数据不足一屏(好比初始值是空的),这个事件也会被触发,须要自行过滤</span>
onEndReachedThreshold
(number):距离最后一个列表元素多少像素时候触发onEndReached
事件
initialListSize
(number):初始化时候渲染多少条数据,若是不写择时逐条渲染
showsVerticalScrollIndicator
(bool):默认状况下,ListView有滚动条,当设置为false的时候不显示该滚动条(继承自ScrollView)
pageSize
(number,仅ListView
有):每次事件循环(每帧)渲染的行数,经常使用于分页,数据请求回来后渲染多少条,不设置则逐条渲染。