亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

React Native 自定義下拉刷新上拉加載的列表的示例

2024-05-06 16:42:45
字體:
來源:轉載
供稿:網友

在移動端開發中列表頁是非常常見的頁面,在React Native中我們一般使用FlatList或SectionList組件實現這些列表視圖。通常列表頁都會有大量的數據需要加載顯示,這時候就用到了分頁加載,因此對于列表組件來說,實現下拉刷新和上拉加載在很多情況下是必不可少的。

本篇文章基于FlatList封裝一個支持下拉刷新和上拉加載的RefreshListView,對原始的FlatList進行封裝之后,再調用上拉和下拉刷新就十分方便了。

下拉刷新的實現十分簡單,這里我們沿用FlatList本身的屬性來實現

onRefresh— 設置此選項后,則會在列表頭部添加一個標準的RefreshControl控件,以便實現“下拉刷新”的功能。同時你需要正確設置refreshing屬性。

refreshing—— bool值,用來控制刷新控件的顯示與隱藏。刷新完成后設為false。

通過這兩個屬性設置我們就可以實現FlatList頭部的刷新操作,控件使用默認的樣式,Android和iOS沿用各自系統的組件來顯示。

重點在于上拉加載更多,React Native的列表組件中沒有這個功能,需要我們自己實現。 對于上拉加載,通常我們有幾種狀態,這里我創建一個RefreshState.js文件存放上拉加載的狀態:

export default { Idle: 'Idle',        // 初始狀態,無刷新的情況 CanLoadMore: 'CanLoadMore', // 可以加載更多,表示列表還有數據可以繼續加載 Refreshing: 'Refreshing',  // 正在刷新中 NoMoreData: 'NoMoreData',  // 沒有更多數據了 Failure: 'Failure'     // 刷新失敗}

然后根據這幾種狀態來封裝一個RefreshFooter組件,使其根據不同狀態顯示不同內容,廢話不多說上代碼:

import React, {Component} from 'react';import {View, Text, ActivityIndicator, StyleSheet, TouchableOpacity} from 'react-native';import RefreshState from './RefreshState';import PropTypes from 'prop-types';export default class RefreshFooter extends Component { static propTypes = {  onLoadMore: PropTypes.func,   // 加載更多數據的方法  onRetryLoading: PropTypes.func, // 重新加載的方法 };  static defaultProps = {  footerRefreshingText: "努力加載中",  footerLoadMoreText: "上拉加載更多",  footerFailureText: "點擊重新加載",  footerNoMoreDataText: "已全部加載完畢" };  render() {  let {state} = this.props;  let footer = null;  switch (state) {   case RefreshState.Idle:    // Idle情況下為null,不顯示尾部組件    break;   case RefreshState.Refreshing:    // 顯示一個loading視圖    footer =     <View style={styles.loadingView}>      <ActivityIndicator size="small"/>      <Text style={styles.refreshingText}>{this.props.footerRefreshingText}</Text>     </View>;    break;   case RefreshState.CanLoadMore:    // 顯示上拉加載更多的文字    footer =     <View style={styles.loadingView}>      <Text style={styles.footerText}>{this.props.footerLoadMoreText}</Text>     </View>;    break;   case RefreshState.NoMoreData:    // 顯示沒有更多數據的文字,內容可以自己修改    footer =     <View style={styles.loadingView}>      <Text style={styles.footerText}>{this.props.footerNoMoreDataText}</Text>     </View>;    break;   case RefreshState.Failure:    // 加載失敗的情況使用TouchableOpacity做一個可點擊的組件,外部調用onRetryLoading重新加載數據    footer =     <TouchableOpacity style={styles.loadingView} onPress={()=>{      this.props.onRetryLoading && this.props.onRetryLoading();     }}>      <Text style={styles.footerText}>{this.props.footerFailureText}</Text>     </TouchableOpacity>;    break;  }  return footer; }}const styles = StyleSheet.create({ loadingView: {  flexDirection: 'row',  justifyContent: 'center',  alignItems: 'center',  padding: 15, }, refreshingText: {  fontSize: 12,  color: "#666666",  paddingLeft: 10, }, footerText: {  fontSize: 12,  color: "#666666" }});

注意,propTypes是我們給RefreshFooter組件定義的給外部調用的方法,方法類型需要使用PropTypes來指定,需要安裝facebook的prop-types依賴庫,最好使用 yarn add prop-types 安裝,不容易出錯。這里用作運行時的類型檢查,可以點擊這里 詳細了解。

defaultProps中我們定義了幾種不同狀態下默認的文本內容,可以在外部傳值進行修改。

接下來就要來實現這個RefreshListView了。首先應該明確的是,這個RefreshListView要有頭部刷新和尾部刷新的調用方法,具體調用數據的方法應該在外部實現。先跟RefreshFooter一樣定義兩個方法:

static propTypes = { onHeaderRefresh: PropTypes.func, // 下拉刷新的方法,供外部調用 onFooterRefresh: PropTypes.func, // 上拉加載的方法,供外部調用};

上面說到頭部的下拉刷新使用FlatList自帶特性實現,我們需要定義一個bool值isHeaderRefreshing來作為refreshing屬性的值,控制頭部顯示與否。同時定義一個isFooterRefreshing來判斷尾部組件的刷新狀態。定義footerState用來設定當前尾部組件的state,作為RefreshFooter的值。

constructor(props) {  super(props);  this.state = {   isHeaderRefreshing: false, // 頭部是否正在刷新   isFooterRefreshing: false, // 尾部是否正在刷新   footerState: RefreshState.Idle, // 尾部當前的狀態,默認為Idle,不顯示控件  } }

render函數如下:

render() {  return (   <FlatList    {...this.props}    onRefresh={()=>{ this.beginHeaderRefresh() }}    refreshing={this.state.isHeaderRefreshing}    onEndReached={() => { this.beginFooterRefresh() }}    onEndReachedThreshold={0.1} // 這里取值0.1(0~1之間不包括0和1),可以根據實際情況調整,取值盡量小    ListFooterComponent={this._renderFooter}   />  ) }  _renderFooter = () => {  return (   <RefreshFooter    state={this.state.footerState}    onRetryLoading={()=>{     this.beginFooterRefresh()    }}   />  ) };

可以看到上面的代碼中有beginHeaderRefresh和beginFooterRefresh兩個方法,這兩個方法就是用來調用刷新的,但是在刷新之前還有一些邏輯情況需要判斷。比如頭部和尾部不能夠同時刷新,不然數據處理結果可能受到影響,正在刷新時要防止重復的刷新操作,這些都是要考慮的。這里我在代碼中詳細注釋了:

/// 開始下拉刷新beginHeaderRefresh() { if (this.shouldStartHeaderRefreshing()) {  this.startHeaderRefreshing(); }}/// 開始上拉加載更多beginFooterRefresh() { if (this.shouldStartFooterRefreshing()) {  this.startFooterRefreshing(); }}/*** * 當前是否可以進行下拉刷新 * @returns {boolean} * * 如果列表尾部正在執行上拉加載,就返回false * 如果列表頭部已經在刷新中了,就返回false */shouldStartHeaderRefreshing() { if (this.state.footerState === RefreshState.refreshing ||  this.state.isHeaderRefreshing ||  this.state.isFooterRefreshing) {  return false; } return true;}/*** * 當前是否可以進行上拉加載更多 * @returns {boolean} * * 如果底部已經在刷新,返回false * 如果底部狀態是沒有更多數據了,返回false * 如果頭部在刷新,則返回false * 如果列表數據為空,則返回false(初始狀態下列表是空的,這時候肯定不需要上拉加載更多,而應該執行下拉刷新) */shouldStartFooterRefreshing() { if (this.state.footerState === RefreshState.refreshing ||  this.state.footerState === RefreshState.NoMoreData ||  this.props.data.length === 0 ||  this.state.isHeaderRefreshing ||  this.state.isFooterRefreshing) {  return false; } return true;}

其中startHeaderRefreshing和startFooterRefreshing的邏輯如下:

/// 下拉刷新,設置完刷新狀態后再調用刷新方法,使頁面上可以顯示出加載中的UI,注意這里setState寫法startHeaderRefreshing() { this.setState(  {   isHeaderRefreshing: true  },  () => {   this.props.onHeaderRefresh && this.props.onHeaderRefresh();  } );}/// 上拉加載更多,將底部刷新狀態改為正在刷新,然后調用刷新方法,頁面上可以顯示出加載中的UI,注意這里setState寫法startFooterRefreshing() { this.setState(  {   footerState: RefreshState.Refreshing,   isFooterRefreshing: true  },  () => {   this.props.onFooterRefresh && this.props.onFooterRefresh();  } );}

在刷新之前,我們需要將頭部或尾部的組件顯示出來,然后再調用外部的數據接口方法。這里setState這樣寫的好處是state中的值更新完成后才會調用箭頭函數中的方法,是有嚴格順序的,如果把 this.props.onFooterRefresh && this.props.onFooterRefresh() 寫在setState外部,在UI上我們可能看不到頭部的loading或者尾部的努力加載中,接口方法就已經調用完畢了。

最后,在刷新結束后我們還需要調用停止刷新的方法,使頭部或尾部組件不再顯示,否則一直是加載中還可能讓人以為是bug。下面看看停止刷新的方法:

/** * 根據尾部組件狀態來停止刷新 * @param footerState * * 如果刷新完成,當前列表數據源是空的,就不顯示尾部組件了。 * 這里這樣做是因為通常列表無數據時,我們會顯示一個空白頁,如果再顯示尾部組件如"沒有更多數據了"就顯得很多余 */endRefreshing(footerState: RefreshState) { let footerRefreshState = footerState; if (this.props.data.length === 0) {  footerRefreshState = RefreshState.Idle; } this.setState({  footerState: footerRefreshState,  isHeaderRefreshing: false,  isFooterRefreshing: false })}

這里傳入一個尾部組件狀態的參數是為了更新尾部組件的樣式。同時對數據源data進行一個判斷,如果為空說明當前沒有數據,可以顯示空白頁面,那么尾部組件也沒必要顯示了。

以下是我使用RefreshListView實現的豆瓣電影頁面分頁加載的效果圖:

完整的Demo地址: https://github.com/mrarronz/react-native-blog-examples/tree/master/Chapter4-PullRefresh/PullRefreshExample

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人欧美一区二区三区在线湿哒哒| 日本视频久久久| 成人网址在线观看| 一区二区三区四区在线观看视频| 久久久噜噜噜久噜久久| 91在线观看免费| 久久久久久中文| 欧美日韩国产成人在线观看| 日韩亚洲欧美成人| 国产精品自拍偷拍视频| 亚洲成人激情图| 国产精品美女www爽爽爽视频| 人体精品一二三区| 亚洲第一页中文字幕| 久久香蕉精品香蕉| 成人午夜在线观看| 久久精品国产久精国产思思| 欧美亚洲另类激情另类| 日韩欧美在线网址| 久久精品国产电影| 91天堂在线观看| 中文字幕欧美日韩精品| 中文字幕精品久久久久| 久久久久久久久久久免费精品| 45www国产精品网站| 国产精品高潮呻吟视频| 91成人天堂久久成人| 国内精品久久久久影院 日本资源| 久久久久久中文字幕| 欧美性猛交xxxx免费看久久久| 久久久中精品2020中文| 视频在线观看一区二区| 国产精品久久9| 91在线视频导航| 久久中国妇女中文字幕| 国产精品成久久久久三级| 在线免费观看羞羞视频一区二区| 日韩在线资源网| 日韩在线不卡视频| 大荫蒂欧美视频另类xxxx| 欧美精品激情在线观看| 欧美乱大交做爰xxxⅹ性3| 欧美成人亚洲成人日韩成人| 国外视频精品毛片| 亚洲国产精品资源| 成人黄色大片在线免费观看| 538国产精品视频一区二区| 91香蕉嫩草影院入口| 在线播放国产一区中文字幕剧情欧美| 精品成人乱色一区二区| 91av在线免费观看视频| 日韩电视剧在线观看免费网站| 国产一区二区成人| 久久夜色精品亚洲噜噜国产mv| 国产精品中文字幕在线观看| 亚洲精品视频二区| 91久久精品一区| 亚洲人高潮女人毛茸茸| 日韩美女写真福利在线观看| 欧美电影免费观看大全| 色综合久久天天综线观看| 日韩综合中文字幕| 91国产视频在线| 日韩欧美黄色动漫| 欧美老女人在线视频| 亚洲欧美精品一区| 亚洲国产精品电影| 日韩精品在线播放| 亚洲第一精品久久忘忧草社区| 亚洲v日韩v综合v精品v| 日本高清不卡的在线| 国产欧美精品一区二区三区介绍| 日韩网站免费观看高清| 日韩欧美视频一区二区三区| 亚洲乱码国产乱码精品精天堂| 国产亚洲视频中文字幕视频| 91黑丝在线观看| 亚洲一级片在线看| 国产亚洲精品一区二区| 日韩av手机在线| 欧美性xxxx在线播放| 成人激情av在线| 国产亚洲成av人片在线观看桃| 日韩在线小视频| 欧美性xxxx极品高清hd直播| 97视频在线观看免费高清完整版在线观看| 国产欧美在线看| 国产精品视频一| 中文字幕亚洲无线码在线一区| 国产99视频精品免视看7| 欧美一区二粉嫩精品国产一线天| 尤物99国产成人精品视频| 欧美久久精品午夜青青大伊人| 欧美中文字幕在线播放| 91美女高潮出水| 久久青草精品视频免费观看| 国产精品99一区| 亚洲第一精品夜夜躁人人爽| 国产精品视频不卡| 久久中文字幕视频| 日韩va亚洲va欧洲va国产| 中文字幕精品久久久久| 日韩女优人人人人射在线视频| 色妞色视频一区二区三区四区| 国产最新精品视频| 清纯唯美亚洲激情| 国外成人性视频| 色www亚洲国产张柏芝| 国产日韩精品一区二区| 97在线精品视频| 亚洲国产天堂久久国产91| 亚洲欧美一区二区三区情侣bbw| 疯狂做受xxxx高潮欧美日本| 精品久久久久国产| 日韩欧美大尺度| 日韩久久精品成人| 疯狂做受xxxx欧美肥白少妇| 久久久亚洲国产天美传媒修理工| 欧美专区福利在线| 亚洲美女视频网站| 国产成人精品视频在线观看| 中文字幕亚洲一区| 亚洲专区国产精品| 91久久在线播放| 青草青草久热精品视频在线网站| 一本色道久久综合狠狠躁篇怎么玩| 久久久国产91| 国产精品极品美女在线观看免费| 日韩久久午夜影院| 国产中文字幕日韩| 国产精品美乳一区二区免费| 国产精品一区二区三区成人| 在线日韩日本国产亚洲| 国产日本欧美视频| 欧美精品成人在线| 亚洲少妇中文在线| 欧洲亚洲免费视频| 色综合久久久久久中文网| 欧美精品18videos性欧| 亚洲91精品在线观看| 91色中文字幕| 欧美日韩日本国产| 亚洲黄色在线观看| 成人国产精品免费视频| 亚洲人成在线观| 久久久99久久精品女同性| 国产精品永久免费| 欧美二区乱c黑人| 亚洲美女www午夜| 国产午夜精品理论片a级探花| 欧美激情一区二区三区久久久| 这里只有精品在线观看| 国产精品狠色婷| 国产精品最新在线观看| 亚洲国产精品电影| 永久免费看mv网站入口亚洲| 大胆欧美人体视频| 69国产精品成人在线播放| 国产精选久久久久久| 91精品国产高清| 欧美激情视频三区| 国产精品免费在线免费| 成人午夜一级二级三级| 精品视频在线播放色网色视频|