React Native_手把手教你做项目(四.上拉加载更多)

在手机应用上,上拉加载更多的功能是必不可少的。同时,在实际使用的时候,当下拉加载,数据仍未返回时,用户多次重复进行下拉加载的操作,为了不产生额外的垃圾数据,我们需要进行判断。同时为了更好的用户体验,增加数据缓存功能。

list.js文件

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, {Component} from 'react';
import {
    Platform,
    StyleSheet,
    Text,
    View,
    ListView,
    TouchableOpacity,
    Image,
    ActivityIndicator,
} from 'react-native';

import Icon from 'react-native-vector-icons/Ionicons';
import Dimensions from 'Dimensions';

const {width, height} = Dimensions.get('window');

import config from '../common/config';
import request from '../common/request';

// Mockjs 解析随机的文字
import  Mock from 'mockjs';

let cachedResult = {
    nexPage: 1,
    item: [],
    total: 0,
}

export default class list extends Component {
    constructor(props) {
        super(props);
        this.state = {
            dataSource: new ListView.DataSource({
                rowHasChanged: (r1, r2)=>r1 !== r2,
            }),
            isLoadingTail: false  //没有加载数据
        }
    }

    //即将显示
    componentWillMount() {
        //加载本地数据
        // this.dsfetchData();
    }

    componentDidMount() {
        //加载网络数据
        this._fetchData(1);
    }

    _fetchData(page) {
        this.setState({
            isLoadingTail: true
        });

        //发送网络请求
        request.get(config.api.base + config.api.list, {
            accessToken: '001',
            a: 'list',
            c: 'data',
            type: 29,
            page: page
        }).then(
            (data) => {
                //将服务器得到的数据缓存进来
                let items = cachedResult.item.concat(data.list);//把缓存的数据进行拼接
                cachedResult.item = items;
                cachedResult.total = items.total;
                console.log(items);
                console.log('总数据是:' + cachedResult.total);
                console.log('当前到了第:' + cachedResult.item.length + '个!');
                this.setState({
                    dataSource: this.state.dataSource.cloneWithRows(
                        cachedResult.item
                    ),
                    isLoadingTail: false
                });
            }
        ).catch(
            (error) => {
                console.log('err' + error);
            }
        )
    }

    // dsfetchData() {
    //     let result = Mock.mock({
    //         "data|20": [
    //             {
    //                 "_id": "@ID",
    //                 "thumb": "@IMG(1024x700,@COLOR(),\'\u56fe\u7247\u4e0a\u7684\u6587\u5b57\')",
    //                 "title": "@cparagraph(1, 3)",
    //                 "video": "\'http:\/\/v.youku.com\/v_show\/id_XMzY5ODY5MDI3Ng==.html?spm=a2h1n.8251846.0.0\'"
    //             }
    //         ],
    //         "success": true
    //     })
    //     this.setState({
    //         dataSource: this.state.dataSource.cloneWithRows(result.data)
    //     })
    // }

    render() {
        return (
            <View style={styles.container}>
                {/*导航条*/}
                <View style={styles.header}>
                    <Text style={styles.headerText}>
                        视频列表
                    </Text>
                </View>
                {/*列表页面*/}
                <ListView
                    dataSource={this.state.dataSource}
                    renderRow={this._renderRow}
                    style={styles.listView}
                    onEndReached={this._fetchMoreData}//滚到底部加载更多数据
                    onEndReachedThreshold={20} //距离底部还有多远触发
                    renderFooter={this._renderFooter}
                />
            </View>
        );
    }

    //自定义Footer视图
    _renderFooter = ()=> {
        if (!this._hasMore() && cachedResult.total !==0) {
            return (
                <View style={styles.loadingMore}>
                    <Text style={styles.loadingText}>没有更多数据啦...</Text>
                </View>
            )
        }
        // if(!this.state.isLoadingTail){
        //     return(<View></View>)
        // }
        //显示一朵小菊花
         return(
             <ActivityIndicator style={styles.loadingMore}></ActivityIndicator>
         )
    }


    //思路:有多种解决方案

    //1.发送请求 2.保存请求参数 3.对比参数

    //刷新请求 2.保存request = refresh 3.对比 refresh==保存request 状态机中的page值
    //状态机 loading = refresh
    //上拉加载更多数据
    _fetchMoreData = ()=> {
        //判断是否有更多数据或者是否在请求中
        if (!this._hasMore || this.isLoadingTail) {
            return
        }

        let page = cachedResult.nexPage;
        //去服务器去加载更多数据
        this._fetchData(page);
    }

    //判断是否还有更多数据
    _hasMore() {
        return cachedResult.item.length !== cachedResult.total;
    }

    //下划线代表内部类自己用的函数,属于规范
    _renderRow = (rowData)=> {
        return (
            <TouchableOpacity>

                {/*整个Cell*/}
                <View style={styles.cellStyle}>
                    {/*标题文字*/}
                    <Text style={styles.title}>{rowData.text}</Text>


                    <Image style={styles.thumb} source={{uri: rowData.profile_image}}>

                    </Image>
                    <Icon name="ios-play"
                          size={30}
                          style={styles.play}
                    />
                    {/*点赞&评论*/}
                    <View style={styles.cellFooter}>
                        {/*点赞*/}
                        <View style={styles.footerBox}>
                            <Icon name="ios-heart-outline"
                                  size={30}
                                  style={styles.boxIcon}
                            />
                            {/*点赞文字*/}
                            <Text style={styles.boxText}>点赞</Text>
                        </View>

                        {/*评论*/}
                        <View style={styles.footerBox}>
                            <Icon name="ios-chatbubbles-outline"
                                  size={30}
                                  style={styles.boxIcon}
                            />
                            {/*点赞文字*/}
                            <Text style={styles.boxText}>评论</Text>
                        </View>
                    </View>
                </View>
            </TouchableOpacity>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#F5FCFF',
    },
    header: {
        // marginTop:Platform.OS == 'ios'?20:0,
        paddingTop: 25,
        paddingBottom: 15,
        backgroundColor: '#dddddd',
        borderBottomWidth: 0.5,
        borderBottomColor: 'black',
    },
    headerText: {
        fontWeight: '600',
        textAlign: 'center',
        fontSize: 16,
    },
    listView: {},
    cellStyle: {
        width: width,
        marginTop: 10,
        backgroundColor: 'white',

    },
    title: {
        padding: 10,
        color: 'black',
        fontSize: 18
    },
    thumb: {
        width: width,
        height: width * 0.56,
        resizeMode: 'cover'
    },
    play: {
        position: 'absolute',
        bottom: 100,
        right: 14,
        width: 46,
        height: 46,
        paddingTop: 8,
        paddingLeft: 18,
        backgroundColor: 'transparent',
        borderColor: 'black',
        borderWidth: 0.5,
        borderRadius: 23,
    },
    cellFooter: {
        flexDirection: 'row',
        justifyContent: 'space-between',
        backgroundColor: '#dddddd',
    },
    footerBox: {
        padding: 10,
        flexDirection: 'row',
        backgroundColor: 'white',
        flex: 1,
        marginLeft: 1,
        justifyContent: 'center',

    },
    boxIcon: {
        fontSize: 22,
        color: '#333',
    },
    boxText: {
        fontSize: 18,
        color: '#333',
        paddingLeft: 12,
        marginTop: 2
    },
    loadingMore:{
       marginVertical:20
    },
    loadingText:{
        fontSize:18,
        color:'#777',
        textAlign:'center'
    }
});

当然,我们使用的是抓包抓到的接口,接口当中没有给出我们需要的total字段,在实际项目中,我们需要跟后台去协调,并给我们数据总量

猜你喜欢

转载自blog.csdn.net/wtdask/article/details/81067851