React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)
在web应用中,上拉刷新加载更多,下拉刷新列表的操作非常常见,那么在react-native中是如何实现呢,我们具体来看一下
reactnative提供了refreshcontrol下拉刷新组件,但是没有提供上拉刷新组件,上拉刷新在app中是很常用的。
今天我们来实现一个ios和android通用的上拉刷新功能。
下面简要介绍下我实现的思路。
思路:
1、常量定义:
const moretext = "加载完毕"; //foot显示的文案 //页码 var pagenum = 1; //每页显示数据的条数 const pagesize = 10; //页面总数据数 var pagecount = 0; //页面list总数据 var totallist = new array(); //foot: 0 隐藏 1 已加载完成 2 显示加载中
2、定义listview
<listview enableemptysections={true} datasource={this.state.datasource} renderrow={this._renderrow.bind(this)} renderfooter={this._renderfooter.bind(this)} onendreached={this._endreached.bind(this)} onendreachedthreshold={0} />
3、声明state状态机变量
listview.datasource实例(列表依赖的数据源)
constructor(props) { super(props); this.state = { datasource: new listview.datasource({ rowhaschanged: (r1, r2) => r1 !== r2, }), loaded: false,//控制request请求是否加载完毕 foot:0,// 控制foot, 0:隐藏foot 1:已加载完成 2 :显示加载中 error:false,
这里我们主要声明了datasource,这个没什么说的
- loaded:用来控制整个页面的菊花
- error:如果request错误,显示一个错误页面
- foot: 控制footer的view
4、渲染页面前,加载数据
componentwillmount() { this._fetchlistdata(); }
5、load服务端数据
_fetchlistdata() { if(pagenum > 1){ this.setstate({loaded:true}); } fetch(requesturl, { method: 'get', headers: headerobj, }).then(response =>{ if (response.ok) { return response.json(); } else { this.setstate({error:true,loaded:true}); } }).then(json=>{ let responsecode = json.code; if (responsecode == 0) { let responsedata = json.data; pagecount = responsedata.count; let list = responsedata.data; if (orderlist == null) { orderlist = []; currentcount = 0; } else { currentcount = list.length; } if(currentcount < pagesize){ //当当前返回的数据小于pagesize时,认为已加载完毕 this.setstate({ foot:1,moretext:moretext}); }else{//设置foot 隐藏footer this.setstate({foot:0}); } for (var i=0; i < list.length; i++) { totallist.push( list[i] ); } this.setstate({ datasource: this.state.datasource.clonewithrows(totallist), loaded: true, }); }else{ this.setstate({error:true,loaded:true}); } }).catch(function (error) { this.setstate({error:true,loaded:true}); }); }
这里的细节挺多的:
1、当pagenum > 1时,就不要整个页面的菊花,此时loaded一直为true,这个主要是为了页面效果,要不然没加载一页数据,这个屏幕就会闪一下。
2、比较当前返回的list的大小,是否小于pagesize,控制footer是否隐藏,还是显示已加载完毕
3、声明了一个全局的totallist对象,每次有新数据的时候,都push进去。
如果不采用push的方式的话,直接采用setstate方法的话,第二页会把第一页的数据覆盖掉。
6、定义renderrow方法
renderrow={this._renderrow.bind(this)} 列表组件渲染函数 ,此处页面逻辑省略。
7、定义renderfooter方法
renderfooter 页脚会在每次渲染过程中都重新渲染。
_renderfooter() { if(this.state.foot === 1){//加载完毕 return ( <view style={{height:40,alignitems:'center',justifycontent:'flex-start',}}> <text style={{color:'#999999',fontsize:12,margintop:10}}> {this.state.moretext} </text> </view>); }else if(this.state.foot === 2) {//加载中 return ( <view style={{height:40,alignitems:'center',justifycontent:'center',}}> <image source={{uri:loadgif}} style={{width:20,height:20}}/> </view>); } }
根据状态机变量foot控制footer的显示
8、onendreached 定义
onendreachedthreshold={0}
当所有的数据都已经渲染过,并且列表被滚动到距离最底部不足onendreachedthreshold个像素的距离时调用。原生的滚动事件会被作为参数传递。译注:当第一次渲染时,如果数据不足一屏(比如初始值是空的),这个事件也会被触发
_endreached(){ if(this.state.foot != 0 ){ return ; } this.setstate({ foot:2, }); this.timer = settimeout( () => { pagenum ++; this._fetchlistdata(); },500); }
这里需要注意一下几点
1、第一屏的时候可能也会触发_endreached方法,所以需要判断foot为非 0(即加载中和已加载完毕)时,直接return
2、上拉时,触发_endreached方法,可能server端接口响应很快,几乎看不到菊花效果,特地加了个500毫秒的等待
9、卸载timer
componentwillunmount() { // 如果存在this.timer,则使用cleartimeout清空。 // 如果你使用多个timer,那么用多个变量,或者用个数组来保存引用,然后逐个clear this.timer && cleartimeout(this.timer); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: Angular排序实例详解