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 = () => ( <View style={{height: 1,backgroundColor: ‘#e0e0e0‘}} /> ) renderFooter = () => { let footer = null let { footerRefreshingText,footerFailureText,footerNoMoreDataText,footerEmptyDataText,footerRefreshingComponent,footerFailureComponent,footerNoMoreDataComponent,footerEmptyDataComponent,} = this.props switch (this.props.refreshState) { case RefreshState.Idle: { footer = (<View style={styles.footerContainer} />) break } case RefreshState.Failure: { footer = ( <TouchableOpacity onPress={() => { 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 : ( <View style={styles.footerContainer}> <Text style={styles.footerText}>{footerFailureText}</Text> </View> )} </TouchableOpacity> ) break } case RefreshState.EmptyData: { footer = ( <TouchableOpacity onPress={() => { this.props.onHeaderRefresh && this.props.onHeaderRefresh(RefreshState.HeaderRefreshing) }} > {footerEmptyDataComponent ? footerEmptyDataComponent : ( <View style={styles.footerContainer}> <Text style={styles.footerText}>{footerEmptyDataText}</Text> </View> )} </TouchableOpacity> ) break } case RefreshState.FooterRefreshing: { footer = footerRefreshingComponent ? footerRefreshingComponent : ( <View style={styles.footerContainer} > <ActivityIndicator size="small" color="#888888" /> <Text style={[styles.footerText,{marginLeft: 7}]}>{footerRefreshingText}</Text> </View> ) break } case RefreshState.NoMoreData: { footer = footerNoMoreDataComponent ? footerNoMoreDataComponent : ( <View style={styles.footerContainer} > <Text style={styles.footerText}>{footerNoMoreDataText}</Text> </View> ) break } } return footer } render() { const {renderItem,...rest} = this.props return ( <FlatList ref={this.props.listRef} {...rest} // 行与行之间的分隔线组件 ItemSeparatorComponent={this.props.disabledSeparator?false:this.renderSeparator} // 列表为空时渲染该组件 ListemptyComponent={this.props.ListemptyComponent} // 头部组件 ListHeaderComponent={this.props.renderHeader} // 尾部组件 ListFooterComponent={this.renderFooter} // 当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用 onEndReached={this.onEndReached} // 刷新组件 refreshControl={ this.props.disabledHeaderRefresh?false:<RefreshControl colors={[‘#00ff00‘,"#9Bd35A","#689F38",]} refreshing={this.props.refreshState == RefreshState.HeaderRefreshing} onRefresh={this.onHeaderRefresh} />} // 决定当距离内容最底部还有多远时触发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;
(1)定义全局变量
// 刷新状态 global.RefreshState = { Idle: 0,// 加载成功 HeaderRefreshing: 1,// 开始下拉刷新 FooterRefreshing: 2,// 开始上拉翻页 NoMoreData: 3,// 加载全部数据 Failure: 4,// 加载失败 EmptyData: 5,// 服务器没有数据 }
(2)通用store
@observable refreshState: 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 ( <ListRow key={item.id} title={item.title} onPress={() => { // 跳转详情页 Actions.homeDetailPage({detail: item}) }} /> ) } <RefreshListView data={toJS(data)} keyExtractor={(item,index) => index.toString()} renderItem={this._renderRow.bind(this)} refreshState={refreshState} onHeaderRefresh={loadData.bind(this.store)} onFooterRefresh={loadMoreData.bind(this.store)} />
3.效果图
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。