Yutt's Blog

React Native 列表组件

2018/01/14 Share

React Native 提供了三种列表组件,分别是:ListView,FlatList 和 SectionList,由于 ListView 已经被弃用,便不再进行详细的说明,本章节主要介绍 FlatList 和 SectionList 的常用属性。

FaltList

高性能的简单列表组件,具有以下便利的特性:

  • 完全跨平台;
  • 支持水平布局模式;
  • 行组件显示或隐藏时可配置回调事件;
  • 支持单独的头部组件;
  • 支持单独的尾部组件;
  • 支持自定义行间分隔线;
  • 支持下拉刷新;
  • 支持上拉加载;
  • 支持跳转到指定行(ScrollToIndex)。

官方例子解析(解决惰性渲染问题)

由于 FlatList 的惰性渲染,当除了 data 属性以外的数据改变时,可能无法导致界面的重新渲染,因此要通过 extraData 属性来解决该问题,下面上代码.

/components/MyList.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React, { Component } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';

class MyListItem extends Component {
_onPress = () => {
this.props._onPressItem(this.props.id);
};

render() {
const textColor = this.props.selected ? 'red' : 'black';
return (
<TouchableOpacity onPress={this._onPress}>
<View>
<Text style={{ color: textColor }}>{this.props.title}</Text>
</View>
</TouchableOpacity>
);
}
}

const MyList = {
MyListItem
};
export default MyList;

/containers/Devices.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import React, { Component } from 'react';
import { FlatList } from 'react-native';
import MyList from '../components/MyListItem';

const data = [
{ id: 1, title: '台式机' },
{ id: 2, title: '笔记本' },
{ id: 3, title: '苹果手机' }
];

class Devices extends Component {
constructor(props) {
super(props);
this.state = {
selected: new Map()
};
}

// 指定是用id代替key
_keyExtrator = item => item.id;

// onPress事件触发,构造列表项可以被选中的效果
_onPressItem = id => {
console.log(id);
this.setState(prevState => {
const selected = new Map(prevState.selected);
selected.set(id, !selected.get(id));
console.log(selected);
return { selected };
});
};

// 列表项渲染
_renderItem = ({ item }) => (
<MyList.MyListItem
id={item.id}
_onPressItem={this._onPressItem}
selected={!!this.state.selected.get(item.id)}
title={item.title}
/>
);

render() {
return (
<FlatList
data={data}
extraData={this.state}
keyExtractor={this._keyExtrator}
renderItem={this._renderItem}
/>
);
}
}

export default Devices;

在这个例子中,构造了“列表项被点击选中时,其内容变红色,再次点击,取消中选中时,其内容变回黑色”这样一个简单的效果,通过父组中 state.selected 来记录相应的列表项是否被选中,同时将改值赋予 FlatList 的 extraData 属性,使其可以被 FlatList 识别。同还用到了其他属性:

  • data (指定填充列表的数据,通常为数组);
  • keyExtractor (react 规定所有数据为数组类型的组件,数组的每一项必须指定一个 key 属性以区别于其他数组项,类似与数据库中的主键,通过该属性,可以自己定制主键属性)。

以此例子为基础,我们来展开对其它属性的学习。

UI 属性

  • ItemSeparatorComponent?: ?ReactClass (行与行之间的分隔线组件。不会出现在第一行之前和最后一行之后。)
  • ListEmptyComponent?: ?ReactClass | React.Element(列表为空时渲染该组件。可以是 React Component, 也可以是一个 render 函数, 或者渲染好的 element。)
  • ListFooterComponent?: ?ReactClass (尾部组件)
  • ListHeaderComponent?: ?ReactClass (头部组件)

/components/MyList.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const ItemSeparatorComponent = () => (
<View style={CommonStyles.separatorLine} />
);

const ListEmptyComponent = () => (
<View style={{ flex: 1, alignItems: 'center', marginTop: 20 }}>
<Text style={CommonStyles.text}>当前没有任何数据!</Text>
</View>
);

const ListHeaderComponent = ({ length = 0 }) => (
<View style={CommonStyles.listHeaderComponent}>
<Text style={CommonStyles.smallText}>当前总共{length}条数据</Text>
</View>
);

const ListFooterComponent = () => (
<View style={CommonStyles.listHeaderComponent}>
<Text style={CommonStyles.smallText}>已经到最下面了</Text>
</View>
);

const MyList = {
MyListItem,
ItemSeparatorComponent,
ListEmptyComponent,
ListHeaderComponent,
ListFooterComponent
};

/containers/Devices.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
render() {
return (
<FlatList
data={data}
extraData={this.state}
keyExtractor={this._keyExtrator}
renderItem={this._renderItem}
ItemSeparatorComponent={MyList.ItemSeparatorComponent}
ListEmptyComponent={MyList.ListEmptyComponent}
ListHeaderComponent={<MyList.ListHeaderComponent lenght={data.length} />}
ListFooterComponent={MyList.ListFooterComponent}
/>
);
}

下拉刷新

  • onRefresh?: ?() => void (如果设置了此选项,则会在列表头部添加一个标准的RefreshControl控件,以便实现“下拉刷新”的功能。同时你需要正确设置refreshing属性。)
  • refreshing?: ?boolean (在等待加载新数据时将此属性设为true,列表就会显示出一个正在加载的符号。)

如果不喜欢默认的刷新器的颜色,可通过指定属性refreshControl来定制舒心器

/components/MyList.js

1
2
3
4
5
6
7
8
9
const MyRefreshControl = ({ refreshing = false, _onRefresh }) => (
<RefreshControl
refreshing={refreshing}
onRefresh={_onRefresh}
title="正在刷新界面"
tintColor={AppColor.THEME}
titleColor={AppColor.FONT}
/>
);

/containers/Devices.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 下拉刷新事件
_onRefresh = () => {
console.log('refresh');
};

<FlatList
data={data}
extraData={this.state}
keyExtractor={this._keyExtrator}
renderItem={this._renderItem}
ItemSeparatorComponent={MyList.ItemSeparatorComponent}
ListEmptyComponent={MyList.ListEmptyComponent}
ListHeaderComponent={
<MyList.ListHeaderComponent lenght={data.length} />
}
ListFooterComponent={MyList.ListFooterComponent}
refreshControl={
<MyList.MyRefreshControl
refreshing={false}
_onRefresh={this._onRefresh}
/>
}
/>

上拉加载

  • onEndReached?: ?(info: {distanceFromEnd: number}) => void (当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用。)

  • onEndReachedThreshold?: ?number (决定当距离内容最底部还有多远时触发onEndReached回调。注意此参数是一个比值而非像素单位。比如,0.5表示距离内容最底部的距离为当前列表可见长度的一半时触发。)

CATALOG
  1. 1. FaltList
    1. 1.1. 官方例子解析(解决惰性渲染问题)
    2. 1.2. UI 属性
    3. 1.3. 下拉刷新
    4. 1.4. 上拉加载