高性能的简单列表组件,支持下面这些经常使用的功能:javascript
若是须要分组/类/区(section),请使用<SectionList>
.java
一个最简单的例子:react
<FlatList
data={[{key: 'a'}, {key: 'b'}]}
renderItem={({item}) => <Text>{item.key}</Text>}
/>
复制代码
下面是一个较复杂的例子,其中演示了如何利用PureComponent
来进一步优化性能和减小 bug 产生的可能(如下这段文字须要你深入理解 shouldComponentUpdate 的机制,以及 Component 和 PureComponent 的不一样,因此若是不了解就先跳过吧)。android
对于MyListItem
组件来讲,其onPressItem
属性使用箭头函数而非 bind 的方式进行绑定,使其不会在每次列表从新 render 时生成一个新的函数,从而保证了 props 的不变性(固然前提是 id
、selected
和title
也没变),不会触发自身无谓的从新 render。换句话说,若是你是用 bind 来绑定onPressItem
,每次都会生成一个新的函数,致使 props 在===
比较时返回 false,从而触发自身的一次没必要要的从新 render。git
给FlatList
指定extraData={this.state}
属性,是为了保证state.selected
变化时,可以正确触发FlatList
的更新。若是不指定此属性,则FlatList
不会触发更新,由于它是一个PureComponent
,其 props 在===
比较中没有变化则不会触发更新。github
keyExtractor
属性指定使用 id 做为列表每一项的 key。segmentfault
class MyListItem extends React.PureComponent { _onPress = () => { this.props.onPressItem(this.props.id); };react-native
render() {
const textColor = this.props.selected ? "red" : "black";
return (
<TouchableOpacity onPress={this._onPress}>
<View>
<Text style={{ color: textColor }}>
{this.props.title}
</Text>
</View>
</TouchableOpacity>
);
}
复制代码
}数组
class MultiSelectList extends React.PureComponent { state = {selected: (new Map(): Map<string, boolean>)};bash
_keyExtractor = (item, index) => item.id;
_onPressItem = (id: string) => {
// updater functions are preferred for transactional updates
this.setState((state) => {
// copy the map rather than modifying state.
const selected = new Map(state.selected);
selected.set(id, !selected.get(id)); // toggle
return {selected};
});
};
_renderItem = ({item}) => (
<MyListItem
id={item.id}
onPressItem={this._onPressItem}
selected={!!this.state.selected.get(item.id)}
title={item.title}
/>
);
render() {
return (
<FlatList
data={this.props.data}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
);
}
复制代码
}
本组件实质是基于<VirtualizedList>
组件的封装,继承了其全部 props(也包括全部<ScrollView>
)的 props),但在本文档中没有列出。此外还有下面这些须要注意的事项:
PureComponent
而非一般的Component
,这意味着若是其props
在浅比较
中是相等的,则不会从新渲染。因此请先检查你的renderItem
函数所依赖的props
数据(包括data
属性以及可能用到的父组件的 state),若是是一个引用类型(Object 或者数组都是引用类型),则须要先修改其引用地址(好比先复制到一个新的 Object 或者数组中),而后再修改其值,不然界面极可能不会刷新。(译注:这一段不了解的朋友建议先学习下js 中的基本类型和引用类型。)keyExtractor
函数来生成 key。本组件若是嵌套在其余同滚动方向的 FlatList 中,则不会继承ScrollView 的 Props。
renderItem
renderItem({ item: Object, index: number, separators: { highlight: Function, unhighlight: Function, updateProps: Function(select: string, newProps: Object) } }) => ?React.Element
复制代码
从data
中挨个取出数据并渲染到列表中。
Provides additional metadata like index
if you need it, as well as a more generic separators.updateProps
function which let you set whatever props you want to change the rendering of either the leading separator or trailing separator in case the more common highlight
and unhighlight
(which set the highlighted: boolean
prop) are insufficient for your use case.
类型 | 必填 |
---|---|
function | 是 |
示例:
<FlatList
ItemSeparatorComponent={Platform.OS !== 'android' && ({highlighted}) => (
<View style={[style.separator, highlighted && {marginLeft: 0}]} /> )} data={[{title: 'Title Text', key: 'item1'}]} renderItem={({item, separators}) => ( <TouchableHighlight onPress={() => this._onPress(item)} onShowUnderlay={separators.highlight} onHideUnderlay={separators.unhighlight}> <View style={{backgroundColor: 'white'}}> <Text>{item.title}</Text> </View> </TouchableHighlight> )} /> 复制代码
data
为了简化起见,data 属性目前只支持普通数组。若是须要使用其余特殊数据结构,例如 immutable 数组,请直接使用更底层的VirtualizedList
组件。
类型 | 必填 |
---|---|
array | 是 |
ItemSeparatorComponent
行与行之间的分隔线组件。不会出如今第一行以前和最后一行以后。 By default, highlighted
and leadingItem
props are provided. renderItem
provides separators.highlight
/unhighlight
which will update the highlighted
prop, but you can also add custom props with separators.updateProps
.
类型 | 必填 |
---|---|
component | 否 |
ListEmptyComponent
列表为空时渲染该组件。能够是 React Component, 也能够是一个 render 函数,或者渲染好的 element。
类型 | 必填 |
---|---|
component, function, element | 否 |
ListFooterComponent
尾部组件。能够是 React Component, 也能够是一个 render 函数,或者渲染好的 element。
类型 | 必填 |
---|---|
component, function, element | 否 |
ListHeaderComponent
头部组件。能够是 React Component, 也能够是一个 render 函数,或者渲染好的 element。
类型 | 必填 |
---|---|
component, function, element | 否 |
columnWrapperStyle
若是设置了多列布局(即将numColumns
值设为大于 1 的整数),则能够额外指定此样式做用在每行容器上。
类型 | 必填 |
---|---|
style object | 否 |
extraData
若是有除data
之外的数据用在列表中(不管是用在renderItem
仍是头部或者尾部组件中),请在此属性中指定。同时此数据在修改时也须要先修改其引用地址(好比先复制到一个新的 Object 或者数组中),而后再修改其值,不然界面极可能不会刷新。
类型 | 必填 |
---|---|
any | 否 |
getItemLayout
(data, index) => {length: number, offset: number, index: number}
复制代码
getItemLayout
是一个可选的优化,用于避免动态测量内容尺寸的开销,不过前提是你能够提早知道内容的高度。若是你的行高是固定的,getItemLayout
用起来就既高效又简单,相似下面这样:
getItemLayout={(data, index) => (
{length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
)}
复制代码
对于元素较多的列表(几百行)来讲,添加getItemLayout
能够极大地提升性能。注意若是你指定了ItemSeparatorComponent
,请把分隔线的尺寸也考虑到 offset 的计算之中。
类型 | 必填 |
---|---|
function | 否 |
horizontal
设置为 true 则变为水平布局模式。
类型 | 必填 |
---|---|
boolean | 否 |
initialNumToRender
指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户呈现可见的内容。注意这第一批次渲染的元素不会在滑动过程当中被卸载,这样是为了保证用户执行返回顶部的操做时,不须要从新渲染首批元素。
类型 | 必填 |
---|---|
number | 否 |
initialScrollIndex
开始时屏幕顶端的元素是列表中的第 initialScrollIndex
个元素, 而不是第一个元素。若是设置了这个属性,则第一批initialNumToRender
范围内的元素不会再保留在内存里,而是直接马上渲染位于 initialScrollIndex
位置的元素。须要先设置 getItemLayout
属性。
类型 | 必填 |
---|---|
number | 否 |
inverted
翻转滚动方向。实质是将 scale 变换设置为-1。
类型 | 必填 |
---|---|
boolean | 否 |
keyExtractor
(item: object, index: number) => string;
复制代码
此函数用于为给定的 item 生成一个不重复的 key。Key 的做用是使 React 可以区分同类元素的不一样个体,以便在刷新时可以肯定其变化的位置,减小从新渲染的开销。若不指定此函数,则默认抽取item.key
做为 key 值。若item.key
也不存在,则使用数组下标。
类型 | 必填 |
---|---|
function | 否 |
numColumns
多列布局只能在非水平模式下使用,即必须是horizontal={false}
。此时组件内元素会从左到右从上到下按 Z 字形排列,相似启用了flexWrap
的布局。组件内元素必须是等高的——暂时还没法支持瀑布流布局。
类型 | 必填 |
---|---|
number | 否 |
onEndReached
(info: {distanceFromEnd: number}) => void
复制代码
当列表被滚动到距离内容最底部不足onEndReachedThreshold
的距离时调用。
类型 | 必填 |
---|---|
function | 否 |
onEndReachedThreshold
决定当距离内容最底部还有多远时触发onEndReached
回调。注意此参数是一个比值而非像素单位。好比,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发。
类型 | 必填 |
---|---|
number | 否 |
onRefresh
() => void
复制代码
若是设置了此选项,则会在列表头部添加一个标准的RefreshControl
控件,以便实现“下拉刷新”的功能。同时你须要正确设置refreshing
属性。
类型 | 必填 |
---|---|
function | 否 |
onViewableItemsChanged
(info: {
viewableItems: array,
changed: array,
}) => void
复制代码
在可见行元素变化时调用。可见范围和变化频率等参数的配置请设置viewabilityConfig
属性。
类型 | 必填 |
---|---|
function | 否 |
progressViewOffset
当须要在指定的偏移处显示加载指示器的时候,就能够设置这个值。
类型 | 必填 | 平台 |
---|---|---|
number | 否 | Android |
legacyImplementation
May not have full feature parity and is meant for debugging and performance comparison.
类型 | 必填 |
---|---|
boolean | 否 |
refreshing
在等待加载新数据时将此属性设为 true,列表就会显示出一个正在加载的符号。
类型 | 必填 |
---|---|
boolean | 否 |
removeClippedSubviews
对于大列表启用本属性可能能够提升性能。
注意:有些状况下会有 bug(好比内容没法显示)。请谨慎使用。
类型 | 必填 |
---|---|
boolean | 否 |
viewabilityConfig
请参考ViewabilityHelper.js
的源码来了解具体的配置。
类型 | 必填 |
---|---|
ViewabilityConfig | 否 |
viewabilityConfig
takes a type ViewabilityConfig
an object with following properties
Property | Required | Type |
---|---|---|
minimumViewTime | No | number |
viewAreaCoveragePercentThreshold | No | number |
itemVisiblePercentThreshold | No | number |
waitForInteraction | No | boolean |
At least one of the viewAreaCoveragePercentThreshold
or itemVisiblePercentThreshold
is required. This needs to be done in the constructor
to avoid following error (ref):
Error: Changing viewabilityConfig on the fly is not supported`
复制代码
constructor (props) {
super(props)
this.viewabilityConfig = {
waitForInteraction: true,
viewAreaCoveragePercentThreshold: 95
}
}
复制代码
<FlatList
viewabilityConfig={this.viewabilityConfig}
...
复制代码
Minimum amount of time (in milliseconds) that an item must be physically viewable before the viewability callback will be fired. A high number means that scrolling through content without stopping will not mark the content as viewable.
Percent of viewport that must be covered for a partially occluded item to count as "viewable", 0-100. Fully visible items are always considered viewable. A value of 0 means that a single pixel in the viewport makes the item viewable, and a value of 100 means that an item must be either entirely visible or cover the entire viewport to count as viewable.
Similar to viewAreaPercentThreshold
, but considers the percent of the item that is visible, rather than the fraction of the viewable area it covers.
Nothing is considered viewable until the user scrolls or recordInteraction
is called after render.
viewabilityConfigCallbackPairs
List of ViewabilityConfig
/onViewableItemsChanged
pairs. A specific onViewableItemsChanged
will be called when its corresponding ViewabilityConfig
's conditions are met. 请参考ViewabilityHelper.js
的源码来了解具体的配置。
类型 | 必填 |
---|---|
array of ViewabilityConfigCallbackPair | 否 |
scrollToEnd()
scrollToEnd([params]);
复制代码
滚动到底部。若是不设置getItemLayout
属性的话,可能会比较卡。
参数:
名称 | 类型 | 必填 | 说明 |
---|---|---|---|
params | object | 否 | 看下面的说明 |
Valid params
keys are:
true
.scrollToIndex()
scrollToIndex(params);
复制代码
将位于指定位置的元素滚动到可视区的指定位置,当viewPosition
为 0 时将它滚动到屏幕顶部,为 1 时将它滚动到屏幕底部,为 0.5 时将它滚动到屏幕中央。
注意:若是不设置
getItemLayout
属性的话,没法跳转到当前渲染区域之外的位置。
参数:
名称 | 类型 | 必填 | 说明 |
---|---|---|---|
params | object | 是 | 看下面的说明 |
Valid params
keys are:
true
.0
places the item specified by index at the top, 1
at the bottom, and 0.5
centered in the middle.scrollToItem()
scrollToItem(params);
复制代码
这个方法会顺序遍历元素。尽量使用scrollToIndex
代替。
注意:若是不设置
getItemLayout
属性的话,没法跳转到当前渲染区域之外的位置。
参数:
名称 | 类型 | 必填 | 说明 |
---|---|---|---|
params | object | 是 | 看下面的说明 |
Valid params
keys are:
true
.scrollToOffset()
scrollToOffset(params);
复制代码
滚动列表到指定的偏移(以像素为单位),等同于ScrollView
的scrollTo
方法。
参数:
名称 | 类型 | 必填 | 说明 |
---|---|---|---|
params | object | 是 | 看下面的说明 |
Valid params
keys are:
horizontal
being true, the offset is the x-value, in any other case the offset is the y-value. Required.true
.recordInteraction()
recordInteraction();
复制代码
主动通知列表发生了一个事件,以使列表从新计算可视区域。好比说当waitForInteractions
为 true 而且用户没有滚动列表时。通常在用户点击了列表项或发生了导航动做时调用。
flashScrollIndicators()
flashScrollIndicators();
复制代码
短暂地显示滚动指示器。