react-native 自定义 下拉刷新 / 上拉加载更多 组件
Posted qiyecao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react-native 自定义 下拉刷新 / 上拉加载更多 组件相关的知识,希望对你有一定的参考价值。
1.封装 Scroller 组件
/** * 下拉刷新/上拉加载更多 组件(Scroller) */ import React, {Component} from ‘react‘; import { StyleSheet, Text, View, ListView, ActivityIndicator, RefreshControl, } from ‘react-native‘; export default class Scroller extends Component { // 构造函数 constructor(props) { super(props); this.state = { // } } render() { const { dataSource, renderRow, isRefreshing } = this.props; // console.log(this.props); return ( <View style={styles.container}> {/*列表数据*/} <ListView // 数据源 dataSource={dataSource} // 从数据源(dataSource)中接受一条数据,以及它和它所在section的ID renderRow={renderRow} // 页头与页脚会在每次渲染过程中都重新渲染(允许在ListView底部增加一栏,便于显示加载动画) renderFooter={this._renderFooter.bind(this)} // 当所有的数据都已经渲染过,并且列表被滚动到距离最底部不足onEndReachedThreshold个像素的距离时调用 onEndReached={this._fetchMoreData.bind(this)} // 调用onEndReached之前的临界值,单位是像素。(预加载) onEndReachedThreshold={20} // 隐藏右侧滚动条 showsVerticalScrollIndicator={false} // finished warning : in next release ... enableEmptySections={true} // 自动调整迁移内容 // 导航栏或标签栏或工具栏不覆盖 Scrollview 内容 // 去除默认定位间距 automaticallyAdjustContentInsets={false} // 下拉刷新 refreshControl={ <RefreshControl // 是否刷新 refreshing={isRefreshing} onRefresh={this._onRefresh.bind(this)} tintColor={"#ff6600"} title={"拼命加载中..."} /> } /> </View> ) } /** * 下拉刷新 */ _onRefresh() { // console.log(‘下拉刷新‘); if (this.props.isRefreshing || !this._hasMore()) { return } // 向后台发送 ‘0‘,告知刷新操作 this.props.fetchData(0); } /** * 加 _ 代表私有方法 * 上拉加载更多 */ _fetchMoreData() { // console.log(‘上拉加载更多‘); /** * this._hasMore() 验证还有更多数据 * isLoadingTail true/false 加载动画(菊花图) */ if (!this._hasMore() || this.props.isLoadingTail) { return } let page = this.props.cachedResults.nextPage; this.props.fetchData(page); } /** * 验证还有更多数据 */ _hasMore() { return this.props.cachedResults.items.length !== this.props.cachedResults.items.total; } /** * 底部加载动画 及 没有更多数据文本(ListView底部增加一栏,便于显示加载动画) */ _renderFooter() { if (!this._hasMore() && this.props.cachedResults.total !== 0) { return ( <View style={styles.loadingMore}> <Text style={styles.loadingText}>没有更多了</Text> </View> ) } if (!this.props.isLoadingTail) { return ( <View style={styles.loadingMore}></View> ) } // 菊花图 return ( <ActivityIndicator style={styles.loadingMore}/> ) } } // 样式 const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: ‘#F5FCFF‘, }, // 菊花图 loadingMore: { marginVertical: 20 }, // 文案样式 loadingText: { color: ‘#777‘, textAlign: ‘center‘ } });
2.页面调用
/** * 视频列表页 */ import React, {Component} from ‘react‘; import { StyleSheet, Text, View, ImageBackground, ListView, TouchableHighlight, Alert, Dimensions, ActivityIndicator, RefreshControl, } from ‘react-native‘; // 下拉刷新/上拉加载更多组件 import Scroller from ‘../../components/Scroller‘; // 图标 import Icon from ‘react-native-vector-icons/Ionicons‘; // item 组件 import CreationItem from ‘../../components/CreationItem‘; import config from ‘../../common/config‘; import request from ‘../../common/request‘; let {width} = Dimensions.get("window"); // 缓存列表中所有数据 let cachedResults = { nextPage: 1, // 下一页 items: [], // listview 数据(视频列表) total: 0 // 总数 }; export default class List extends Component { // 构造函数 constructor() { super(); let ds = new ListView.DataSource({ // 比较两条数据是否是一样的,来判断数据是否发生改变 rowHasChanged: (r1, r2) => r1 !== r2 }); this.state = { dataSource: ds.cloneWithRows([]), isLoadingTail: false, // loading? isRefreshing: false // refresh? } } render() { return ( <View style={styles.container}> {/*顶部标题栏*/} <View style={styles.header}> <Text style={styles.headerTitle}>列表页面</Text> </View> {/*列表数据*/} <Scroller // 数据源 dataSource={this.state.dataSource} // 渲染item(子组件) renderRow={this._renderRow.bind(this)} // 是否可以刷新 isRefreshing={this.state.isRefreshing} // 是否可以加载更多 isLoadingTail={this.state.isLoadingTail} // 请求数据 fetchData={this._fetchData.bind(this)} // 缓存列表数据 cachedResults={cachedResults} /> </View> ) } // 生命周期-组件挂载完毕 请求数据 componentDidMount() { this._fetchData(1); } // 请求数据 _fetchData(page) { let that = this; if (page !== 0) { // 加载更多操作 this.setState({ isLoadingTail: true }); } else { // 刷新操作 this.setState({ isRefreshing: true }); // 初始哈 nextPage cachedResults.nextPage = 1; } request .get(config.api.base + config.api.creations, { accessToken: ‘abc‘ }) // data 变化的新数据 .then((data) => { if (data.success) { // 保存原数据 let items = cachedResults.items.slice(); if (page !== 0) { // 加载更多操作 // 数组拼接 items = items.concat(data.data); cachedResults.nextPage += 1; } else { // 刷新操作 // 数据不变 items = data.data; } cachedResults.items = items; // 视频列表数据 cachedResults.total = data.total; // 总数 setTimeout(function () { if (page !== 0) { // 加载更多操作 that.setState({ isLoadingTail: false, dataSource: that.state.dataSource.cloneWithRows(cachedResults.items) }); } else { // 刷次操作 that.setState({ isRefreshing: false, dataSource: that.state.dataSource.cloneWithRows(cachedResults.items) }); } }, 1000); } }) .catch((error) => { if (page !== 0) { // 上拉加载更多操作 this.setState({ isLoadingTail: false }); } else { this.setState({ // 刷新操作 isRefreshing: false }); } console.error(error); }); } // 列表 Item _renderRow(row) { const { navigation } = this.props; return ( <CreationItem navigation={navigation} key={row.id} // 子组件唯一性 row={row} /> ) } } // 样式 const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: ‘#F5FCFF‘, }, // 头部样式 header: { paddingTop: 25, paddingBottom: 12, backgroundColor: ‘#ee735c‘, }, // 头部title样式 headerTitle: { color: ‘#fff‘, fontSize: 16, textAlign: ‘center‘, fontWeight: ‘600‘ }, // 菊花图 loadingMore: { marginVertical: 20 }, // 文案样式 loadingText: { color: ‘#777‘, textAlign: ‘center‘ } });
以上是关于react-native 自定义 下拉刷新 / 上拉加载更多 组件的主要内容,如果未能解决你的问题,请参考以下文章
react-native使用flatlist上拉加载下拉刷新