react native基于FlatList下拉刷新上拉加載實(shí)現(xiàn)代碼示例
react native 的上拉加載一直困擾著自己,一直用的第三方組件,但是可維護(hù)性不高,而且也不太好用,最近工作沒那么忙,就研究下了官方的FlatList,做出來的成果,比第三方組件流暢度高好多,而且也很好用
官方介紹:https://reactnative.cn/docs/flatlist/
下面是效果圖:

ios效果圖

android效果圖
總體思路就是:就是計算屏幕高度,然后減去導(dǎo)航的頭部,根據(jù)列表高度計算出每頁的個數(shù),然后向上取整。這樣做的目的是:防止不滿屏狀態(tài)下的,onEndReached函數(shù)的主動觸發(fā)。
方法實(shí)現(xiàn):
//滿屏頁面判斷
fullScreenJusting(ItemHeight) {
const screnHeight = screnInfo.size.height; //屏幕高度
//計算列表個數(shù)
const listNum = (screnHeight - 40) / ItemHeight;
return Math.ceil(listNum);
}
下拉刷新用的是 RefreshControl
官網(wǎng)地址:https://reactnative.cn/docs/refreshcontrol/#progressbackgroundcolor
具體代碼:
import React, { Component } from 'react';
import {
View,
Text,
Image,
StyleSheet,
FlatList,
RefreshControl,
ActivityIndicator,
} from 'react-native';
import { SafeAreaView } from 'react-navigation';
import screnInfo from '../utils/View';
import BaseStyle from '../constants/Style';
import { QUESTION_LIST } from '../constants/Api';
import { form_req } from '../utils/Request';
export default class TestScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: [
],
refreshing: false,
fresh: true,
animating: true,
nomore: false,
pageSize: 0,
pageNumber: 1,
};
}
componentDidMount() { //初始化的時候要判斷長度 控制上拉加載
const ListNums = this.fullScreenJusting(50);
this.setState({
pageSize: ListNums
})
this.onEndReachedCalled = false;
this.getOrderList(ListNums, 1, true);
}
//滿屏頁面判斷
fullScreenJusting(ItemHeight) {
const screnHeight = screnInfo.size.height; //屏幕高度
//計算列表個數(shù)
const listNum = (screnHeight - 40) / ItemHeight;
return Math.ceil(listNum);
}
getOrderList(ListNums, pageNumber, fresh) {
let nomore;
form_req(QUESTION_LIST, {
page: pageNumber,
perpage: ListNums,
}).then(res => {
if (res.code == 200) {
const item = res.data;
if (item.length < ListNums) {
nomore = true
} else {
nomore = false
}
if (fresh) {
this.setState({
data: item,
nomore: nomore
})
} else {
this.setState({
data: this.state.data.concat(item),
nomore: nomore,
})
}
// this.onEndReachedCalledDuringMomentum = true;
} else {
}
});
}
renderItem = item => {
return (
<View style={styles.item} key={item.id}>
<Text>{item.name}</Text>
</View>
);
};
//列表線
ItemSeparatorComponent = () => {
return <View style={styles.baseLine} />;
};
//頭部
ListHeaderComponent = () => { };
//尾部
ListFooterComponent = () => {
return (
<View style={styles.bottomfoot}>
{
this.state.data.length != 0 ?
this.state.nomore ? (
<Text style={styles.footText}>- 我是有底線的 -</Text>
) : (
<View style={styles.activeLoad}>
<ActivityIndicator size="small" animating={this.state.animating} />
<Text style={[styles.footText, styles.ml]}>加載更多...</Text>
</View>
)
:
null
}
</View>
);
};
//為空時
ListEmptyComponent() {
return (
<View style={styles.noListView}>
{/* <Image
style={styles.noListImage}
source={require('../images/status/order_no_record.png')}
/> */}
<Text style={styles.NoListText}>暫無訂單</Text>
</View>
);
}
_keyExtractor = (item,index) => item.id;
_onEndReached = () => {
if (!this.state.nomore && this.onEndReachedCalled ) {
this.getOrderList(this.state.pageSize, ++this.state.pageNumber, false);
}
this.onEndReachedCalled=true;
};
_onRefresh() {
this.setState({ nomore: false, pageNumber: 1 }, () => {
this.getOrderList(this.state.pageSize, 1, true);
})
}
render() {
return (
<SafeAreaView style={BaseStyle.flex}>
<View style={styles.listConten}>
<FlatList
data={this.state.data}
keyExtractor={this._keyExtractor}
onEndReached={this._onEndReached}
refreshing={true}
renderItem={({ item }) => this.renderItem(item)}
ItemSeparatorComponent={this.ItemSeparatorComponent}
ListEmptyComponent={this.ListEmptyComponent}
ListFooterComponent={this.ListFooterComponent}
onEndReachedThreshold={0.1}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
colors={['#ff0000', '#00ff00', '#0000ff']}
progressBackgroundColor={"#ffffff"}
onRefresh={() => {
this._onRefresh();
}}
/>
}
/>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
listConten: {
flex: 1,
backgroundColor: '#ffffff',
},
item: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: "center",
backgroundColor: '#ffffff',
height: 50,
},
baseLine: {
width: screnInfo.size.width,
height: 1,
backgroundColor: '#eeeeee',
},
noListView: {
width: screnInfo.size.width,
height: screnInfo.size.height - 140,
justifyContent: 'center',
alignItems: 'center',
},
NoListText: {
marginTop: 15,
fontSize: 18,
color: '#999999',
},
noListImage: {
width: 130,
height: 140,
},
bottomfoot: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 10,
},
footText: {
marginTop: 5,
fontSize: 12,
color: '#999999',
},
activeLoad: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
ml: {
marginLeft: 10,
},
});
這里的坑就是:當(dāng)初始化進(jìn)來頁面的時候 上拉會主動觸發(fā),所以這里加了一個開關(guān) this.onEndReachedCalled = false; 初始化給一個false 當(dāng)觸發(fā)了 設(shè)為true,放在調(diào)取接口之后

代碼都很簡單易懂~ 有什么不懂的,或者有什么問題請留言,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
react+antd4實(shí)現(xiàn)優(yōu)化大批量接口請求
這篇文章主要為大家詳細(xì)介紹了如何使用react hooks + antd4實(shí)現(xiàn)大批量接口請求的前端優(yōu)化,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-02-02
react源碼中的生命周期和事件系統(tǒng)實(shí)例解析
這篇文章主要為大家介紹了react源碼中的生命周期和事件系統(tǒng)實(shí)例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
詳解React項(xiàng)目中eslint使用百度風(fēng)格
這篇文章主要介紹了React項(xiàng)目中eslint使用百度風(fēng)格,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09
react render props模式實(shí)現(xiàn)組件復(fù)用示例
本文主要介紹了react render props模式實(shí)現(xiàn)組件復(fù)用示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
React?正確使用useCallback?useMemo的方式
這篇文章主要介紹了React?正確使用useCallback?useMemo的方式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-08-08

