1.下拉刷新/上拉加载更多 组件(RefreshListView)
src/components/RefreshListView/index.js
/** * 下拉刷新/上拉加载更多 组件(RefreshListView) */import React, {PureComponent} from 'react';import PropTypes from 'prop-types';import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, ViewPropTypes, RefreshControl} from 'react-native'const RefreshState = { Idle: 0, HeaderRefreshing: 1, FooterRefreshing: 2, NoMoreData: 3, Failure: 4, EmptyData: 5,}class RefreshListView extends PureComponent { static propTypes = { data: PropTypes.array.isRequired, renderItem: PropTypes.func.isRequired, refreshState: PropTypes.number.isRequired, listRef: PropTypes.node, onHeaderRefresh: PropTypes.func, footerContainerStyle: ViewPropTypes.style, footerTextStyle: ViewPropTypes.style, disabledSeparator: PropTypes.bool, disabledHeaderRefresh: PropTypes.bool, footerRefreshingText: PropTypes.string, footerFailureText: PropTypes.string, footerNoMoreDataText: PropTypes.string, footerEmptyDataText: PropTypes.string, ListEmptyComponent: PropTypes.node, footerRefreshingComponent: PropTypes.node, footerFailureComponent: PropTypes.node, footerNoMoreDataComponent: PropTypes.node, footerEmptyDataComponent: PropTypes.node, } static defaultProps = { disabledHeaderRefresh: false, footerRefreshingText: '数据加载中…', footerFailureText: '点击重新加载', footerNoMoreDataText: '已加载全部数据', footerEmptyDataText: '暂时没有相关数据', } componentWillReceiveProps(nextProps) {} componentDidUpdate(prevProps, prevState) {} onHeaderRefresh = () => { if (this.shouldStartHeaderRefreshing()) { this.props.onHeaderRefresh(RefreshState.HeaderRefreshing) } } onEndReached = () => { if (this.shouldStartFooterRefreshing()) { this.props.onFooterRefresh && this.props.onFooterRefresh(RefreshState.FooterRefreshing) } } shouldStartHeaderRefreshing = () => { if (this.props.refreshState == RefreshState.HeaderRefreshing || this.props.refreshState == RefreshState.FooterRefreshing) { return false } return true } shouldStartFooterRefreshing = () => { const {refreshState, data} = this.props if (data.length == 0) { return false } return (refreshState == RefreshState.Idle) } renderSeparator = () => () renderFooter = () => { let footer = null let { footerRefreshingText, footerFailureText, footerNoMoreDataText, footerEmptyDataText, footerRefreshingComponent, footerFailureComponent, footerNoMoreDataComponent, footerEmptyDataComponent, } = this.props switch (this.props.refreshState) { case RefreshState.Idle: { footer = ( ) break } case RefreshState.Failure: { footer = ( { if (this.props.data.length == 0) { this.props.onHeaderRefresh && this.props.onHeaderRefresh(RefreshState.HeaderRefreshing) } else { this.props.onFooterRefresh && this.props.onFooterRefresh(RefreshState.FooterRefreshing) } }} > {footerFailureComponent ? footerFailureComponent : ( ) break } case RefreshState.EmptyData: { footer = ()} {footerFailureText} { this.props.onHeaderRefresh && this.props.onHeaderRefresh(RefreshState.HeaderRefreshing) }} > {footerEmptyDataComponent ? footerEmptyDataComponent : ( ) break } case RefreshState.FooterRefreshing: { footer = footerRefreshingComponent ? footerRefreshingComponent : ()} {footerEmptyDataText} ) break } case RefreshState.NoMoreData: { footer = footerNoMoreDataComponent ? footerNoMoreDataComponent : ( {footerRefreshingText} ) break } } return footer } render() { const {renderItem, ...rest} = this.props return ( {footerNoMoreDataText} } // 决定当距离内容最底部还有多远时触发onEndReached回调 onEndReachedThreshold={0.1} // 根据行数据data,渲染每一行的组件 renderItem={renderItem} /> ) }}const styles = StyleSheet.create({ footerContainer: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', padding: 10, height: 44, }, footerText: { fontSize: 14, color: '#555555', },})export { RefreshState,}export default RefreshListView;
2.页面调用
(1)定义全局变量
// 刷新状态global.RefreshState = { Idle: 0, // 加载成功 HeaderRefreshing: 1, // 开始下拉刷新 FooterRefreshing: 2, // 开始上拉翻页 NoMoreData: 3, // 加载全部数据 Failure: 4, // 加载失败 EmptyData: 5, // 服务器没有数据}
(2)通用store
@observablerefreshState: any;/** * 改变refreshState的值 * @param refreshState */@action setRefreshState(refreshState) { this.refreshState = refreshState}
(3)当前 store
// 加载成功this.setRefreshState(RefreshState.Idle);if(!res.data.topics.length){ // 服务器没有数据 this.setRefreshState(RefreshState.EmptyData);}
(4)页面
const { data, refreshState, loadData, loadMoreData } = this.store;// 新闻列表store = new NewsStore(); // 子组件渲染_renderRow(obj) { let item = obj.item; return ({ // 跳转详情页 Actions.homeDetailPage({detail: item}) }} /> )} index.toString()} renderItem={this._renderRow.bind(this)} refreshState={refreshState} onHeaderRefresh={loadData.bind(this.store)} onFooterRefresh={loadMoreData.bind(this.store)}/>
3.效果图