长列表或者无限下拉列表是最常见的应用场景之一。RN 提供的 ListView 组件,在长列表这种数据量大的场景下,性能堪忧。而在最新的 0.43 版本中,提供了 FlatList 组件,或许就是你需要的高性能长列表解决方案。它足以应对大多数的长列表场景。

一、属性说明

 <FlatList      data={showData}renderItem={this._renderItem}getItemLayout={(data,index)=>({length:115,offset:115*index,index})}refreshing={isRefresh}onRefresh={this._onRefresh}onEndReached={() => this._onLoadMore()}onEndReachedThreshold={0.1}ListFooterComponent={this._renderFooter}ItemSeparatorComponent={this._separator}keyExtractor={item => item.infoId}/>

data

为一个Array,列表的数据来源,数组中的每一项,需要包含 key 值作为唯一标示

keyExtractor

此函数用于为给定的item生成一个不重复的key。Key的作用是使React能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。若不指定此函数,则默认抽取data中item.key作为key值。若item.key也不存在,则必须使用下列方法添加一个唯一的标识。

keyExtractor={(item, index) => item.infoId}

否则会出下图所示的黄色警告

renderItem

负责渲染列表中的每个item。

_renderItem({item,index}){let {pic,title,runDistance,registTime,userName,price} = item;return(<View key={index} style={styles.listItem}><Image source={{uri:pic}} style={styles.cheyuanPic}/><View style={styles.rightBox}><Text style={styles.cheyuanTitle} ellipsizeMode='tail' numberOfLines={1}>{title}</Text><Text style={styles.cheyuanJianjie}>{registTime} {runDistance}</Text><Text style={styles.cheyuanJianjie}>{userName}</Text><View style={styles.priceBox}><Text style={styles.cheyuanPrice}>{price}万</Text></View></View></View>)}

getItemLayout

可选优化项。但是实际测试中,如果不做该项优化,性能会差很多。所以强烈建议做此项优化! 如果不做该项优化,每个列表都需要事先渲染一次,动态地取得其渲染尺寸,然后再真正地渲染到页面中。

如果预先知道列表中的每一项的高度(ITEM_HEIGHT)和其在父组件中的偏移量(offset)和位置(index),就能减少一次渲染。这是很关键的性能优化点

getItemLayout={(data,index)=>({length:115,offset:115*index,index})}

refreshing、onRefresh组合用于下拉刷新

refreshing:

在等待加载新数据时将此属性设为true,列表就会显示出一个正在加载的符号。

onRefresh:

如果设置了此选项,则会在列表头部添加一个标准的RefreshControl 控件,以便实现“下拉刷新”的功能。同时你需要正确设置refreshing 属性。

onEndReached、onEndReachedThreshold、ListFooterComponent组合用于上拉加载

上拉加载的关键onEndReached,当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用。注意:onEndReachedThreshold的值不是像素单位而是比值,例如,0.5表示距离内容最底部的距离为当前列表可见长度的一半时触发。

我们可以利用官方组件 RefreshControl实现下拉刷新功能,但React Native官方没有提供相应的上拉加载的组件,因此在RN中实现上拉加载比下拉刷新要复杂一点。
虽然没有直接提供上拉加载的组件,不过我们仍可以通过ActivityIndicator以及FlatList的onEndReached与onEndReachedThreshold、ListFooterComponent属性来实现相应效果。

1.ActivityIndicator
这里上拉加载的转圈效果用ActivityIndicator表现。在开始上拉加载的实现之前先介绍一下官方组件ActivityIndicator——加载指示器。ActivityIndicator的使用很简单。

2.根据以上可以实现一个简单的初始加载页面

renderLoadingView(){return(<View style={styles.container}><ActivityIndicator animating={true}color='red'size="large"/></View>)}

3.ListEmptyComponent (当然这个方法是RN0.45才开始有的)
列表为空时渲染该组件。由于我用的0.44,这里就自己控制一下,实现一个列表数据为空的页面

renderEmptyView(){return (<View style={styles.listEmpty}><Image style={styles.default_img}source={{uri: "https://img.58cdn.com.cn/escstatic/fecar/pmuse/chejian_list/momren.png"}} /><Text style={styles.default_content}>您暂无符合此筛选条件的车源</Text></View>);}

4.渲染列表数据

renderData(){let {showData,isRefresh} = this.state;return(<FlatList data={showData}renderItem={this._renderItem}getItemLayout={(data,index)=>({length:115,offset:115*index,index})}refreshing={isRefresh}onRefresh={this._onRefresh}onEndReached={() => this._onLoadMore()}onEndReachedThreshold={0.1}ListFooterComponent={this._renderFooter}ItemSeparatorComponent={this._separator}keyExtractor={item => item.infoId}/>)}

5.上拉加载的尾部动画通过FlatList的ListFooterComponent属性,来控制尾部组件的渲染
这里第二页以后尾部才开始展示,没有更多数据时进行提示

_renderFooter(){let {hasMorePage,page}=this.state;if(hasMorePage && page>=2){return(<View style={styles.footer}><ActivityIndicator /><Text>正在加载更多数据...</Text></View>)}else if(!hasMorePage && page>=2) {return(<View style={{height:30,alignItems:'center',justifyContent:'flex-start',}}><Text style={{color:'#999999',fontSize:14,marginTop:5,marginBottom:5,}}>没有更多数据了</Text></View>)}else {return (<View style={styles.footer}><Text></Text></View>);}}

ItemSeparatorComponent属性用来控制分割组件的渲染

_separator(){return <View style={{height:1,backgroundColor:'lightgray'}}/>;}

最后,附上源码

import React, {PureComponent} from 'react';import {View, StyleSheet, Text, Image, FlatList, ActivityIndicator, Dimensions} from 'react-native';
let totalWidth=Dimensions.get('window').width;
export default class FlatListDemo extends PureComponent {constructor(props){super(props);this.state={showData:[],noData:false,isRefresh:false,isLoading:true,page:1,listSize:null,hasMorePage:true,loadingMore:false};this._onRefresh=this._onRefresh.bind(this);this._renderFooter=this._renderFooter.bind(this);}render(){let {isLoading,noData} = this.state;if (isLoading){return this.renderLoadingView();}else if(!noData && !isLoading){return this.renderData()}else if(noData && !isLoading){return this.renderEmptyView()}}_renderItem({item,index}){let {pic,title,runDistance,registTime,userName,price} = item;return(<View key={index} style={styles.listItem}><Image source={{uri:pic}} style={styles.cheyuanPic}/><View style={styles.rightBox}><Text style={styles.cheyuanTitle} ellipsizeMode='tail' numberOfLines={1}>{title}</Text><Text style={styles.cheyuanJianjie}>{registTime} {runDistance}</Text><Text style={styles.cheyuanJianjie}>{userName}</Text><View style={styles.priceBox}><Text style={styles.cheyuanPrice}>{price}万</Text></View></View></View>)}_onRefresh(){this.setState({isRefresh:true,page:1},()=>{this.getShowData(1,'refresh')})}_onLoadMore(){if((this.state.page - 1) * 20 < this.state.listSize && !this.state.loadingMore){this.setState({loadingMore:true},()=>{this.getShowData(this.state.page);})}else if((this.state.page - 1) * 20 >= this.state.listSize && !this.state.loadingMore){this.setState({hasMorePage:false})}}getShowData(page,type){fetch(`https://cheapi.58.com/cst/getPriceTop?brand=408844&series=409052&cid=304&pageIndex=${page}`).then(res=>res.json()).then(data=>{if(data.status===0 && data.result.infoMap.listSize!==0){let dateAry = data.result.infoMap.InfoList.map(item => {return item.infoMap;});if(type==='refresh'){this.setState({showData:[...dateAry],page:this.state.page+1,isRefresh:false,isLoading:false,noData:false,loadingMore:false,listSize:data.result.infoMap.listSize})}else {this.setState({showData:[...this.state.showData,...dateAry],page:this.state.page+1,isRefresh:false,isLoading:false,noData:false,loadingMore:false,listSize:data.result.infoMap.listSize})}}else if(data.status===0 && data.result.infoMap.listSize===0){this.setState({noData:true,showData:[],page:this.state.page+1,isRefresh:false,isLoading:false,loadingMore:false,listSize:data.result.infoMap.listSize})}})}componentDidMount(){this.getShowData(1);}renderLoadingView(){return(<View style={styles.container}><ActivityIndicator animating={true}color='red'size="large"/></View>)}renderData(){let {showData,isRefresh} = this.state;return(<FlatList data={showData}renderItem={this._renderItem}getItemLayout={(data,index)=>({length:115,offset:115*index,index})}refreshing={isRefresh}onRefresh={this._onRefresh}onEndReached={() => this._onLoadMore()}onEndReachedThreshold={0.1}ListFooterComponent={this._renderFooter}ItemSeparatorComponent={this._separator}keyExtractor={item => item.infoId}/>)}renderEmptyView(){return (<View style={styles.listEmpty}><Image style={styles.default_img}source={{uri: "https://img.58cdn.com.cn/escstatic/fecar/pmuse/chejian_list/momren.png"}} /><Text style={styles.default_content}>您暂无符合此筛选条件的车源</Text></View>);}_renderFooter(){let {hasMorePage,page}=this.state;if(hasMorePage && page>=2){return(<View style={styles.footer}><ActivityIndicator /><Text>正在加载更多数据...</Text></View>)}else if(!hasMorePage && page>=2) {return(<View style={{height:30,alignItems:'center',justifyContent:'flex-start',}}><Text style={{color:'#999999',fontSize:14,marginTop:5,marginBottom:5,}}>没有更多数据了</Text></View>)}else {return (<View style={styles.footer}><Text></Text></View>);}}_separator(){return <View style={{height:1,backgroundColor:'lightgray'}}/>;}
}const styles = StyleSheet.create({container:{flex:1,width:totalWidth,justifyContent: 'center',alignItems:'center',backgroundColor: '#F5FCFF'},listItem:{height:115,width:totalWidth,backgroundColor: '#FFFFFF',paddingLeft:15,paddingTop:15,paddingRight:15,flexDirection: 'row'},cheyuanPic:{height: 80,width:105},rightBox:{flex:1,marginLeft:10,height:80},cheyuanTitle:{fontFamily: 'PingFangSC-Semibold',fontSize: 14,color: '#333333',},cheyuanJianjie:{fontFamily: 'PingFangSC-Regular',fontSize: 12,color: '#999999'},priceBox:{marginTop:5},cheyuanPrice:{fontFamily: 'PingFangSC-Semibold',fontSize: 13,color: '#FF552E'},footer:{flexDirection:'row',height:24,justifyContent:'center',alignItems:'center',marginBottom:10,},listEmpty:{flex:1,width:totalWidth,justifyContent: 'center',alignItems:'center',},default_img:{width:90,height:90,marginBottom:20},default_content:{fontFamily: 'PingFangSC-Regular',fontSize: 15,height: 21,color: '#CCCCCC',textAlign: 'center'}
});

RN FlatList组件相关推荐

  1. RN FlatList使用详解及源码解析

    FlatList使用详解及源码解析 前言 长列表或者无限下拉列表是最常见的应用场景之一.RN 提供的 ListView 组件,在长列表这种数据量大的场景下,性能堪忧.而在最新的 0.43 版本中,提供 ...

  2. ReactNative简介、开发环境、调试、常用组件、useState状态、FlatList组件、SectionList组件、Platform 模块、定义样式、图片组件、触摸事件、打包apk发布版

    ReactNative简介: ReactNative是基于React语法来进行开发移动app的框架: ReactNative中提供了移动端专用的一些组件,我们要使用ReactNative固有的组件代替 ...

  3. FlatList组件的使用

    上一篇博客介绍了ScrollableTabView组件,其中封装了一个CategoryList组件,这篇博客介绍一下这个组件的封装,其实看下图很简单的,就是一个FlatList组件,但还是第一次使用还 ...

  4. react native 中下拉列表FlatList组件的讲解以及实例demo

    RN中的下拉列表组件.以前RN的下拉列表是listView,但是这个组件的性能不咋地.当数据较多的时候就会很卡.所以RN就新出了一个FaltList组件来代替它.这里我们简单总结一下新的下拉组件. 一 ...

  5. RN自定义组件封装 - 播放类似PPT动画

    1. 前言 近日,被安排做一个开场动画的任务.虽然RN提供了Animated来自定义动画,但是本次动画中的元素颇多,交互甚烦...在完成任务的同时,发现很多步骤其实是重复的,于是封装了一个小组件记录一 ...

  6. RN FlatList

    RN列表开发, RN应该是3.0 注意版本 /*** Created by blocknew on 2019/10/15.*/ /* jshint esversion: 6 */ import Rea ...

  7. FlatList组件onViewableItemsChanged实现左右列表联动

    onViewableItemsChanged简介 FlatList是React Native提供的一个高性能的列表组件,本身具备了列表Item缓存复用的逻辑,并且还支持下拉刷新等功能.在列表开发中,特 ...

  8. RN子组件获取redux数据

    一.可以用Provider组件包起要用redux数据的组件,传给他store <Provider store={store}><App/><Index/> < ...

  9. RN PickerView组件

    pickerView多滚轮选中组件 1.功能说明 页面底部弹出的半屏滚轮选择弹窗 目前仅支持到双滚轮,三滚轮的后期再扩展 2.组件效果 单滚轮 双滚轮 3.数据格式 单滚轮数据 {option: [{ ...

最新文章

  1. 机器学习 —— 概率图模型(学习:CRF与MRF)
  2. 【RecyclerView】 十、RecyclerView 数据更新 ( 增加单条数据 | 批量增加数据 )
  3. electron android编译,Tiny4412_Android编译步骤
  4. 计算机组成原理 陈泽,江西师范大学-计算机组成原理的期末复习.doc
  5. SQL Server之视图基础知识
  6. Tomcat6 ,servlet配置(可用)
  7. Mysql报错130_mysql 突然报错,连接不上
  8. 《CCIE路由和交换认证考试指南(第5版) (第1卷)》——1.6节虚拟交换系统
  9. 制作openstack-centos镜像
  10. java 语法 泛型_java-解密泛型语法
  11. 3年开发经验,挂在了MyBatis十八连环问上!精通MyBatis源码,有多吃香?
  12. 用MySQL写怎么删除字母_mysql如何替换掉字母
  13. 真正的mybatis_redis二级缓存
  14. 博客园自定义主题样式
  15. 网上的很多Android项目源码有用吗?Android开发注意的地方。
  16. mysql管理数据 并上传至云端_西部数码网站管理助手创建、导入恢复、导出备份mysql数据库...
  17. linux 时区异常修正
  18. 实用!使用Mac内置功能一键转换繁体与简体中文
  19. BackgroundWorker的参数传递
  20. 现代优化算法 (一):模拟退火算法 及应用举例

热门文章

  1. QQ音乐/酷狗音乐锁屏控制实现原理
  2. php codeIgniter 框架引入第三方类库文件
  3. electron 获取屏幕
  4. Windows更新之后,无法进入系统,重置此电脑,释放空间,再试一次
  5. python语言表白语句简单_100句简短表白情话 表白语句大全
  6. 政企办公新入口,华为云桌面安全便捷更高效!
  7. 无形资产递延所得税费用确认
  8. 材料好还是计算机好,塑料PC材质好还是PP好,PP、PC、PE有何区别?哪个更好?哪个更贵?...
  9. JS获取页面class相同的控件
  10. C语言Sizeof()