react native关于FlatList的随手记

FlatList

注意:
1. 滑出渲染区域后,内部状态不保留,请确保组件以外保留了数据

		2. 为了优化内存占用同时保持滑动顺畅,列表内容会在屏幕外绘制,如果滑动速度超

			过渲染速度,则会先看到空白内容
		
		3. 继承自pureComponent 而非通常的Component,意味着props在浅比较中是相等的
			
			则不会重新渲染
		
		4. 默认情况下每行需要提供一个不重复的key属性,也可以提供一个keyExtractor函数来生成key

1. itemSeparatorComponent:

分割线,不会出现在第一行之前和最后一行之后

2. ListEmptyComponent:

	列表为空时渲染该组件,可以是React.Component 也可以是render函数/渲染好的element

3. ListFooterComponent:

尾部组件,可以实现加载更多尾部

4. ListHeaderComponent:

	头部组件,当界面包含其他元素和列表的时候,可以将其他元素作为header放到

ListHeaderComponent 中

5. columnWrapperStyle:

如果设置了多布局(column > 1) ,则可以额外指定次央视作用在每个容器上

6. data:

设置列表数据,为了简化起见,data 属性目前只支持普通数组

7. extraData:

		如果有除data以外的数据用在列表中(不论是用在renderItem还是头部或者尾部组件
		
	中),请在此属性中指定。同时此数据在修改时也需要先修改其引用地址(比如先复制
	
	到一个新的 Object 或者数组中),然后再修改其值,否则界面很可能不会刷新。

8. getItemLayout:

	可选的优化,避免动态测量内容尺寸的开销,前提是提前知道内容的高度,如果行高固

定,getItemLayout用起来高效又简单

 getItemLayout={(data, index) => (
    {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
  )}

注意:
如果设置了分隔线,分隔线的尺寸也要计算到offset中

9. horizonal:

true 变为水平布局模式

10. initialNumToRender:

	指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户

呈现可见的内容。

注意:

	注意这第一批次渲染的元素不会在滑动过程中被卸载,这样是为了保证
	
用户执行返回顶部的操作时,不需要重新渲染首批元素。

11. initialScrollIndex:

	开始时屏幕顶端的元素是列表中的第 initialScrollIndex个元素, 而不是第一个元素。如果

设置了这个属性,则第一批initialNumToRender范围内的元素不会再保留在内存里,而是直		

接立刻渲染位于 initialScrollIndex 位置的元素。需要先设置 getItemLayout 属性。

12. keyExtractor:

	此函数用于为给定的 item 生成一个不重复的 key。Key 的作用是使 React 能够区分同类

元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。若不指

定此函	数,则默认抽取item.key作为 key 值。若item.key也不存在,则使用数组下标。

13. numColumn:

	多列布局只能在非水平模式下使用,即必须是horizontal={false}。此时组件内元素会从左

到右从上到下按 Z 字形排列,类似启用了flexWrap的布局。组件内元素必须是等高的——		

暂时还无法支持瀑布流布局。

14. onEndReached:

当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用。

15. onEndReachedThreshold:

	决定当距离内容最底部还有多远时触发onEndReached回调。注意此参数是一个比值而

非像素单位。比如,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发。

16. onRefresh

	如果设置了此选项,则会在列表头部添加一个标准的RefreshControl控件,以便实现“下

拉刷新”的功能。同时你需要正确设置refreshing属性。

17. regreshing:

在等待加载新数据时将此属性设为 true,列表就会显示出一个正在加载的符号。

18. onViewableItemsChanged:

	在可见行元素变化时调用。可见范围和变化频率等参数的配置请设置viewabilityConfig属

性。

19. renderItem:

从data中挨个取出数据并渲染到列表中。

item (Object): The item from data being rendered.

index (number): The index corresponding to this item in the data array.

separators (Object)

	highlight (Function)

	unhighlight (Function)

	updateProps (Function)

	select (enum('leading', 'trailing'))

	newProps (Object)

示例,包含下拉刷新和上拉加载更多

import React, {Component} from 'react';
import {Text, View, StyleSheet, FlatList, Image, StatusBar} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import ToastUtil from '../base/ToastUtil';


export default class TrainNavigation extends Component {

    state = {
        barStyle: 'dark-content',
        trainList: [],
        currentPage: 1,
        isRefresh: false,
        isLoadMore: false,
        isHasNext: true,
        showFooter: 0,
    };

    static navigationOptions = {
        tabBarLabel: '训练',
        tabBarIcon: ({focused}) => {
            if (focused) {
                return (<Image style={styles.tabbaricon} source={require('../assets/train_selected.png')}/>
                );
            } else {
                return (<Image style={styles.tabbaricon} source={require('../assets/train.png')}/>
                );
            }
        },
    };

    componentDidMount() {
        this._navListener = this.props.navigation.addListener('didFocus', () => {
            StatusBar.setBarStyle('dark-content');
            StatusBar.setBackgroundColor('white');
            this.getTrainData(this.state.currentPage);
        });
    }

    componentWillUnmount() {
        this._navListener.remove();
    }

    renderFooterComponent() {
        const showFooter = this.state.showFooter;
        if (showFooter === 0) {
            return (
                <View>

                </View>
            );
        } else if (showFooter === 1) {
            return (
                <View style={{alignItems: 'center', justifyContent: 'center', marginTop: 10, marginBottom: 10}}>
                    <Text style={{color: 'rgba(186, 191, 194, 1)', fontSize: 12}}>加载更多数据</Text>
                </View>
            );
        } else {
            return (
                <View style={{alignItems: 'center', justifyContent: 'center', marginTop: 10, marginBottom: 10}}>
                    <Text style={{color: 'rgba(186, 191, 194, 1)', fontSize: 12}}>- 没有更多了,下周再来吧 -</Text>
                </View>
            );
        }
    }

    onRefresh() {
        if (!this.state.isRefresh) {
            let currentPage = 1;
            this.setState({currentPage: currentPage, isRefresh: true});
            this.getTrainData(currentPage);
        }
    }

    onLoadMore() {

        if (!this.state.isLoadMore && this.state.trainList.length > 0 && this.state.isHasNext) {
            let currentPage = this.state.currentPage;
            currentPage++;
            this.getTrainData(currentPage);
            this.setState({
                currentPage: currentPage,
                isLoadMore: true,
            });
        }
    }


    async getTrainData(currentPage) {
        try {
            let token = await AsyncStorage.getItem(appConfig.USER_TOKEN);
            let response = await fetch(httpurl.BASE_URL + url.url_train_list, {
                method: 'POST',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                    'Authorization': token,
                },
                body: JSON.stringify({'pageNum': currentPage}),
            });
            const newVar = await response.json();
            switch (newVar.code) {
                case 200:
                    let {trainList, showFooter} = this.state;
                    if (currentPage == 1) {
                        if (null !== trainList && trainList.length > 0) {
                            trainList = [];
                        }
                    }
                    const busPlans = newVar.data.busPlans;
                    trainList = [...trainList, ...busPlans];
                    if (null !== trainList && trainList.length > 0) {
                        if (newVar.data.hasNextPage) {
                            showFooter = 1;
                        } else {
                            showFooter = 2;
                        }
                    } else {
                        showFooter = 0;
                    }


                    this.setState({
                        trainList: trainList,
                        isHasNext: newVar.data.hasNextPage,
                        isLoadMore: false,
                        isRefresh: false,
                        showFooter: showFooter,
                    });
                    break;
                case 401:

                    break;
                default:
                    ToastUtil.show(newVar.message);
                    currentPage--;
                    this.setState({
                        isLoadMore: false,
                        isRefresh: false,
                        currentPage: currentPage,
                    });
                    break;
            }
        } catch (e) {
            currentPage--;
            this.setState({
                isLoadMore: false,
                isRefresh: false,
                currentPage: currentPage,
            });
        }
    }

    test() {
        var obj = {
            name: '123',
            age: 12,
        };

        let array = [
            {
                name: ' 2342',
            },
            {
                name: '12312',
            },
        ];
        const array1 = array.map(item => {
            return {
                item,
                checked: false,
            };
        });

        const selectedList = array1.filter(item => item.checked);

    }
// item布局
    renderItem(item, index) {
        return (
            <View style={styles.itemViewStyle}>
                <View style={{
                    width: 343, height: 150, marginTop: 10,
                    marginBottom: 10,
                }}>
                    <Image style={styles.itemImageStyle}
                           hide={true}
                           source={{uri: item.photo}}/>
                    <View style={{
                        width: '100%',
                        height: '100%',
                        position: 'absolute',
                        borderRadius: 5,
                        backgroundColor: item.state === 0 ? 'rgba(0,0,0,0.25)' : 'rgba(0, 0, 0, 0.6)',
                        justifyContent: 'flex-end',
                    }}>
                        {item.state === 0 ? <Text
                                style={{
                                    fontSize: 22,
                                    color: 'white',
                                    fontWeight: 'bold',
                                    marginLeft: 12,
                                }}>{item.title} </Text> :
                            <View style={{flexDirection: 'row'}}>
                                <Image style={{width: 30, height: 30, marginLeft: 12}}
                                       source={require('../assets/ic_clock.png')}/>
                                <Text style={{
                                    fontSize: 22,
                                    color: 'white',
                                    fontWeight: 'bold',
                                }}>{item.title} </Text></View>}

                        {/*"Day" + (position + 1) + " · " + bean.getMinute() + "分钟"*/}
                        <Text style={{
                            fontSize: 12,
                            color: 'rgba(222, 222, 222, 1)',
                            fontWeight: 'bold',
                            marginLeft: 12,
                            marginBottom: 9,
                        }}>{'Day' + index + 1 + ' . ' + item.minute + '分钟'} </Text>
                    </View>
                </View>


            </View>
        );
    }

    renderEmptyComponent() {
        return (
            <View style={{
                width: '100%',
                height: '100%',
                backgroundColor: 'white',
                justifyContent: 'center',
                alignItems: 'center',
            }}>
                <Image style={{width: 343, height: 238, marginTop: 143}}
                       source={require('../assets/ic_train_empty.png')}/>
                <Text style={{color: 'rgba(99, 109, 118, 1)', fontSize: 18}}>活动暂未开启,快来报名参加吧!</Text>
            </View>
        );
    }

    render() {
        const {trainList, isRefresh} = this.state;

        return (
            <View style={{height: '100%', backgroundColor: 'rgba(255, 255, 255, 1)'}}>
                <StatusBar
                    barStyle={'dark-content'}
                    hidden={false}
                    translucent={false}
                    backgroundColor={'white'}/>
                <View style={styles.headerView}>
                    <Text style={styles.titleText}>训练计划</Text>
                </View>
                <Text style={[styles.titleText, {
                    fontSize: 13,
                    marginLeft: 18,
                    marginBottom: 3,
                }]}>{trainList.length > 0 ? '请您在保障自身安全情况下,根据自身情况完成相应计划。' : ''}</Text>
                <FlatList
                    data={trainList}
                    renderItem={({item, index}) => this.renderItem(item, index)}
                    keyExtractor={(item, index) => index.toString()}
                    onRefresh={() => this.onRefresh()}
                    refreshing={isRefresh}
                    onEndReached={() => this.onLoadMore()}
                    onEndReachedThreshold={0.1}
                    ListFooterComponent={() => this.renderFooterComponent()}
                    ListEmptyComponent={() => this.renderEmptyComponent()}
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    headerView: {
        width: '100%',
        height: 44,
        backgroundColor: 'white',
        flexDirection: 'row',
        alignItems: 'center',
    },
    tabbaricon: {
        width: 24,
        height: 24,
    },
    titleText: {
        marginLeft: 16,
        fontSize: 18,
        color: 'rgba(99, 109, 118, 1)',
    },
    itemViewStyle: {
        position: 'relative',
        justifyContent: 'flex-end',
        alignItems: 'center',
    },
    itemImageStyle: {
        width: 343,
        height: 150,
        borderRadius: 5,
        resizeMode: 'cover',


    },
});



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值