FlatList组件的使用

上一篇博客介绍了ScrollableTabView组件,其中封装了一个CategoryList组件,这篇博客介绍一下这个组件的封装,其实看下图很简单的,就是一个FlatList组件,但还是第一次使用还是出现了很多问题。
CategoryList组件的视图

render() {
    return (
        <FlatList
            numColumns={4}
            style={styles.container}
            data={this.state.data}
            keyExtractor={(info) => info.index}
            initialNumToRender={24}
            getItemLayout={(data, index) => (
                {length: ScreenHelper.scale(315), offset: ScreenHelper.scale(315) * index, index}
            )}
            renderItem={this.renderItem.bind(this)}
            ListFooterComponent={this._renderFooter.bind(this)}
            onEndReached={this._onEndReached.bind(this)}
            onEndReachedThreshold={0.5}
            ItemSeparatorComponent={this._separator}/>
    );
}

这是一个FlatList组件,用于渲染如上图所示的页面

numColumns={num} //可以设置一行渲染几个,比如我这里设置num=4,就是一行渲染四个。
data={this.state.data} //设置数据源,FlatList的数据源是一个简单的Array
initialNumToRender={24} //初始渲染几个,这里设置为我一次请求的数据量24,因为进行了分页加载。
//getItemLayout是一个可选的优化,用于避免动态测量内容尺寸的开销,不过前提是你可以提前知道内容的高度。如果你的行高是固定的,getItemLayout用起来就既高效又简单。
(data, index) => {length: number, offset: number, index: number}
getItemLayout={(data, index) => (
		{length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
)}
//对于元素较多的列表(几百行)来说,添加getItemLayout可以极大地提高性能。注意如果你指定了ItemSeparatorComponent,请把分隔线的尺寸也考虑到 offset 的计算之中。
getItemLayout={(data, index) => (
       {length: ScreenHelper.scale(315), offset: ScreenHelper.scale(315) * index, index}
)}
renderItem={this.renderItem.bind(this)} //渲染每一个Item的方法
ItemSeparatorComponent={this._separator()}/> //渲染分割线的方法
_separator = () => {
    return (<View style={{height: ScreenHelper.scale(10)}}/>);
};

在渲染分割线的时候,我出现了一个错误,就是this._separator()加上了括号,这样会爆出来一个错误:
在这里插入图片描述
这样是因为,你加上括号返回的就不是分割线这个布局了,而是返回了一串字符串对象,所以 此处应该是

ItemSeparatorComponent={this._separator}/>

这里我进行了分页加载,所以还有三个方法:

ListFooterComponent={this._renderFooter.bind(this)}//当每一页结束时FlatList渲染的尾部布局
onEndReached={this._onEndReached.bind(this)} //当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用。
onEndReachedThreshold={0.5} //决定当距离内容最底部还有多远时触发onEndReached回调。此参数是一个比值而非像素单位。比如,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发。
_renderFooter(){
    if (this.state.showFoot === 1) {
        return (
            <View style={{height:30,alignItems:'center',justifyContent:'flex-start',}}>
                <Text style={{color:'#999999',fontSize:14,marginTop:5,marginBottom:5,}}>
                    没有更多数据了
                </Text>
            </View>
        );
    } else if(this.state.showFoot === 2) {
        return (
            <View style={styles.footer}>
                <ActivityIndicator />
                <Text>正在加载更多数据...</Text>
            </View>
        );
    } else if(this.state.showFoot === 0){
        return (
            <View style={styles.footer}>
                <Text></Text>
            </View>
        );
    }
}
_onEndReached(){
    //如果是正在加载中或没有更多数据了,则返回
    if(this.state.showFoot !== 0 ){
        return ;
    }
    //如果当前页大于或等于总页数,那就是到最后一页了,返回
    if((this.state.pageNo!==1) && (this.state.showFoot===1)){
        return;
    } else {
        console.log(this.state.pageNo);
    }
    //底部显示正在加载更多数据
    this.setState({showFoot:2});
    //获取数据
    this.fetchData();
}
//数据请求方法以及数据处理
fetchData() {
    let dataSource=null;//
    let dataBlob = []; //
    let params = {
        "classification": this.classification,
        "category": this.category,
        "pageNo": this.state.pageNo,
        "pageSize": 24,
    };//此处是POST请求方法,故设置请求参数
    let options = {
        method: "POST",
        headers: {
            Accept: "application/json",
            "Content-Type": "application/json"
        },
        body: JSON.stringify(params),
    };
    fetch('http://27.223.99.143:11181/read/read/xxx', options)
        .then(response => {
            if (response.ok) {
                return response.json();
            } else {
                this.setState({
                    isLoading: false,
                    error: true
                })
            }
        })
        .then(responseJson => {
            if (responseJson.err_no === '200') {
                dataSource=responseJson.SST.list;//将数据设置到一个数组中
                let i = 0;
                dataSource.map(function (item) {
                    dataBlob.push(item);
                    i++;
                });//对数据进行遍历,将数据加入到一个dataBlob钟
                let foot = 0;
                if(i<24){
                    foot = 1;//listView底部显示没有更多数据了
                }
                this.setState({
                    //每次加载更多数据时,复制数据,改变state中的data数据源
                    data:this.state.data.concat(dataBlob),
                    isLoading: true,
                    showFoot:foot,
                    pageNo:this.state.pageNo+1,//pageNo+1,下次请求数据的参数设置
                });
                dataSource = null;
                dataBlob = null;
            } else {
                this.setState({
                    isLoading: false,
                    error: true,
                })
            }
        })
        .catch(err => {
            //todo 设置error状态,结束loading状态
            this.setState({
                isLoading: false,
                error: true,
            })
        }).done();
}

二十来天,从没有接触过,到做出来一个小的功能模块,虽然有很多东西参考别人做的,模块还存在很多问题,但在这个过程中,自己学会了很多东西。

未来还会有更多的挑战等着我,加油!!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值