首页 > 编程 > JavaScript > 正文

React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)

2019-11-19 16:06:26
字体:
来源:转载
供稿:网友

在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,这个没什么说的

  1. loaded:用来控制整个页面的菊花
  2. error:如果Request错误,显示一个错误页面
  3. 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); } 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表