ReactNative学习笔记十一之FlatList

作者: mymdeep | 来源:发表于2017-07-26 17:33 被阅读18030次

    之前使用的组件是ListView,当时要添加一个下拉刷新,上拉加载的功能,所以对ListView做了一些封装,但是后来看官方文档,不建议再使用ListView,因为效率问题,做过Android的朋友都知道,Android的ListView如果不自己处理一下,也是有效率问题的。所以官方又推出了FlatList,而且自带上拉下拉的功能。


    功能简介

    • 完全跨平台。
    • 支持水平布局模式。
    • 行组件显示或隐藏时可配置回调事件。
    • 支持单独的头部组件。
    • 支持单独的尾部组件。
    • 支持自定义行间分隔线。
    • 支持下拉刷新。
    • 支持上拉加载。
    • 支持跳转到指定行(ScrollToIndex)。
      如果需要分组/类/区(section),请使用SectionList(这个我们会在之后的文章中介绍)

    使用

    FlatList如果只做简单使用也是很简单的,这里我们会分难以程度,逐渐介绍:

    直接使用

    <FlatList
      data={[{key: 'a'}, {key: 'b'}]}
      renderItem={({item}) => <Text>{item.key}</Text>}
    />
    

    可以看出跟之前的ListView很像,但是其中少了dataSource,这里,我们只需要传递数据,其它的都交给FlatList处理好了。

    属性说明

    • ItemSeparatorComponent
      行与行之间的分隔线组件。不会出现在第一行之前和最后一行之后。�在这里可以根据需要插入一个view

    • ListEmptyComponent
      列表为空时渲染该组件。可以是React Component, 也可以是一个render函数, 或者渲染好的element。

    • ListFooterComponent
      尾部组件

    • ListHeaderComponent
      头部组件

    • columnWrapperStyle
      如果设置了多列布局(即将numColumns
      值设为大于1的整数),则可以额外指定此样式作用在每行容器上。

    • data
      为了简化起见,data属性目前只支持普通数组。如果需要使用其他特殊数据结构,例如immutable数组,请直接使用更底层的VirtualizedList
      组件。

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

    • getItem
      获取每个Item

    • getItemCount
      获取Item属相

    • getItemLayout
      是一个可选的优化,用于避免动态测量内容尺寸的开销,不过前提是你可以提前知道内容的高度。如果你的行高是固定的getItemLayout
      用起来就既高效又简单,类似下面这样:
      getItemLayout={(data, index) => ( {length: 行高, offset: 行高 * index, index} )}注意如果你指定了SeparatorComponent,请把分隔线的尺寸也考虑到offset的计算之中。

    • horizontal
      设置为true则变为水平布局模式。

    • initialNumToRender
      指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户呈现可见的内容。注意这第一批次渲染的元素不会在滑动过程中被卸载,这样是为了保证用户执行返回顶部的操作时,不需要重新渲染首批元素。

    • initialScrollIndex
      指定渲染开始的item index

    • keyExtractor
      此函数用于为给定的item生成一个不重复的key。Key的作用是使React能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。若不指定此函数,则默认抽取item.key作为key值。若item.key也不存在,则使用数组下标。

    • legacyImplementation
      设置为true则使用旧的ListView的实现。

    • numColumns
      多列布局只能在非水平模式下使用,即必须是horizontal={false}
      。此时组件内元素会从左到右从上到下按Z字形排列,类似启用了flexWrap的布局。组件内元素必须是等高的——暂时还无法支持瀑布流布局。

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

    • onEndReachedThreshold
      决定当距离内容最底部还有多远时触发onEndReached
      回调。注意此参数是一个比值而非像素单位。比如,0.5表示距离内容最底部的距离为当前列表可见长度的一半时触发。

    • onRefresh
      如果设置了此选项,则会在列表头部添加一个标准的RefreshControl
      控件,以便实现“下拉刷新”的功能。同时你需要正确设置refreshing
      属性。

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

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

    • renderItem
      根据行数据data,渲染每一行的组件。这个参照下面的demo

    • viewabilityConfig
      请参考ViewabilityHelper
      的源码来了解具体的配置。

    方法

    • scrollToEnd
      滚动到底部。如果不设置getItemLayout
      属性的话,可能会比较卡。

    • scrollToIndex
      滚动到指定index的item
      如果不设置getItemLayout
      属性的话,无法跳转到当前可视区域以外的位置。

    • scrollToItem
      滚动到指定item,如果不设置getItemLayout
      属性的话,可能会比较卡。

    • scrollToOffset
      滚动指定距离

    进阶使用

    在这里我准备了一份代码示例:

    
    const {width,height}=Dimensions.get('window')
    export default class Main extends Component{
        // 构造
        constructor(props) {
            super(props);
        }
        refreshing(){
            let timer =  setTimeout(()=>{
                        clearTimeout(timer)
                        alert('刷新成功')
                    },1500)
        }
        _onload(){
            let timer =  setTimeout(()=>{
                clearTimeout(timer)
                alert('加载成功')
            },1500)
        }
        render() {
            var data = [];
            for (var i = 0; i < 100; i++) {
                data.push({key: i, title: i + ''});
            }
    
            return (
                <View style={{flex:1}}>
                    <Button title='滚动到指定位置' onPress={()=>{
                        this._flatList.scrollToOffset({animated: true, offset: 2000});
                    }}/>
                    <View style={{flex:1}}>
                        <FlatList
                            ref={(flatList)=>this._flatList = flatList}
                            ListHeaderComponent={this._header}
                            ListFooterComponent={this._footer}
                            ItemSeparatorComponent={this._separator}
                            renderItem={this._renderItem}
                            onRefresh={this.refreshing}
                            refreshing={false}
                            onEndReachedThreshold={0}
                            onEndReached={
                                this._onload
                            }
                            numColumns ={3}
                            columnWrapperStyle={{borderWidth:2,borderColor:'black',paddingLeft:20}}
    
                            //horizontal={true}
    
                            getItemLayout={(data,index)=>(
                            {length: 100, offset: (100+2) * index, index}
                            )}
    
                            data={data}>
                        </FlatList>
                    </View>
    
                </View>
            );
        }
    
    
        _renderItem = (item) => {
            var txt = '第' + item.index + '个' + ' title=' + item.item.title;
            var bgColor = item.index % 2 == 0 ? 'red' : 'blue';
            return <Text style={[{flex:1,height:100,backgroundColor:bgColor},styles.txt]}>{txt}</Text>
        }
    
        _header = () => {
            return <Text style={[styles.txt,{backgroundColor:'black'}]}>这是头部</Text>;
        }
    
        _footer = () => {
            return <Text style={[styles.txt,{backgroundColor:'black'}]}>这是尾部</Text>;
        }
    
        _separator = () => {
            return <View style={{height:2,backgroundColor:'yellow'}}/>;
        }
    
    
    }
    const styles=StyleSheet.create({
        container:{
    
        },
        content:{
            width:width,
            height:height,
            backgroundColor:'yellow',
            justifyContent:'center',
            alignItems:'center'
        },
        cell:{
            height:100,
            backgroundColor:'purple',
            alignItems:'center',
            justifyContent:'center',
            borderBottomColor:'#ececec',
            borderBottomWidth:1
    
        },
        txt: {
            textAlign: 'center',
            textAlignVertical: 'center',
            color: 'white',
            fontSize: 30,
        }
    
    })
    

    运行效果如下:

    总结

    总体来说Flatlist还是比ListView用起来方便的,而且提供的功能更多。


    之前文章合集:
    Android文章合集
    iOS文章合集
    ReactNative文章合集
    如果你也做ReactNative开发,并对ReactNative感兴趣,欢迎关注我的公众号,加入我们的讨论群:

    相关文章

      网友评论

      • 稳_e089:你好啊
        请问一下 item的点击时间怎末写 啊
        ???
        蜗牛学开车:<TouchableOpacity style={styles.item} activeOpacity={1} onPress={() => this.clickItem(item)}>
        <Text style={styles.txt}>{item.content}</Text>
        </TouchableOpacity>
      • 一往情深_b560:SectionList 你有用过吗, 设置了SectionSeparatorComponent 后 , ListHeaderComponent也会显示,怎么才能让ListHeaderComponent不显示,置null 没效果
        mymdeep:@一往情深_b560 您可以扫码入群,群里有一些React的专业开发人员
      • 蓝精灵112:initialScrollIndex 这个属性我在ios上应用成果,但是在android上就会出现 界面未渲染的情况
        mymdeep:@蓝精灵112 45版本之后有些bug,我们一直没升级,你可以查一下
        蓝精灵112:@mymdeep 是因为版本太低还是因为版本不匹配
        mymdeep:@蓝精灵112 这个问题之前有人反映过,好像是跟rn的版本有关
      • MarsYang:你好,请问一下,我的flatlist在横向的时候,分割线不显示!不知道怎么回事?如果我添加了高度,它会显示出来,但是是在数据的下边,很奇怪!
      • Tepid_z:请问可以发下Demo吗
      • 走在字里行间:请教一下,我用你的代码运行, _onload这个方法在绘制界面的时候执行了一次,当我再次上拉的时候没有执行这个方法,是什么原因
        走在字里行间:@mymdeep 谢谢
        mymdeep:@走在字里行间 没到边界,不会触发
        mymdeep:@走在字里行间 打印一下那个边界距离
      • 111浪子111:请教一下,cell如何能动态计算高度,我看你的代码里面<Text style={[{flex:1,height:100,backgroundColor:bgColor},styles.txt]}>{txt}</Text>,高度是写死的100
        111浪子111:@mymdeep 多谢
        mymdeep:@111浪子111 你可以改变cell中render的那个view的高度试一下

      本文标题:ReactNative学习笔记十一之FlatList

      本文链接:https://www.haomeiwen.com/subject/zbcokxtx.html