React Native从入门到深入--组件ListView的使

作者: Zax_Smile | 来源:发表于2016-09-14 11:52 被阅读2767次

    此文章中,包括简单的布局,九宫格布局和头视图的使用小demo

    前言

    在iOS开发中,用的最多的一个控件就是TableView,ListView和TableView实现的效果一下,是React Native中的核心组件,高效的用于显示一个可以垂直滚动变化的数据列表。

    TableView的工作原理是:先加载UI,有数据源之后再刷新界面。

    ListView的工作原理是:想创建一个ListView.DataSource数据源,然后给他传递一个普通的的数据组,在使用数据源来实例化一个ListView组件。使用renderRow回调函数,接受数组中的每个数组作为参数,返回一个可渲染的组件。

    一、ListView常用属性

    ListView  继承ScrollerView相关的样式属性

    DataSource   数据属性

    initialListSize  number 

     控制组件刚挂载的时候渲染多少行数据,用来确保首屏显示合适数量的数据,而不是花费太多帧逐步显示出来。

    onEndReachedThreshold  number 

     设置什么时候偏移量达到设置的临界值调用onEndReached

    pageSize  number  

    每帧渲染的行数

    removeClippedSubviews  bool   

    该属性用于提供大数据列表的滚动性能。该使用的时候需要给每一行(row)的布局添加over:'hidden'样式。该属性默认是开启状态。

    scrollRenderAheadDistance  number 

    当一行接近屏幕范围多少像素之内的时候,开始渲染这一行。

    IOS   stickyHeaderIndices[number]

    一个子视图下标的数组,用于决定哪些成员会在滚动之后固定在屏幕顶端。 

    function属性

    onChangeVisibleRows  (visibleRows,changedRows)=>void  

     当可见的行发生变化的时候回调该方法。 

    onEndReached  

    当所有的数据都已经渲染过,并且列表被滚动到距离最底部不足onEndReachedThreshold个像素的距离时调用原生的滚动事件会被作为参数传递。

    注意:当第一次渲染时,如果数据不足一屏(比如初始值是空的),这个事件也会被触发。

    renderFooter  ()=>renderable  

    在每次渲染过程中头和尾总会重新进行渲染。如果发现该重新绘制的性能开销比较大的时候,可以使用StaticContainer容器或者其他合适的组件。

    renderHeader  在每一次渲染过程中Footer(尾)该会一直在列表的底部,header(头)该会一直在列表的头部,用法同上。

    renderRow   (rowData,sectionID,rowID,highlightRow)=>renderable

    该方法有四个参数,其中分别为数据源中一条数据,分组的ID,行的ID,以及标记是否是高亮选中的状态信息。

    renderScrollComponent   (props)=>renderable  

    该方法可以返回一个可以滚动的组件。默认该会返回一个ScrollView

    renderSectionHeader  (sectionData,sectionID)=>renderable

    如果设置了该方法,这样会为每一个section渲染一个粘性的header视图。该视图粘性的效果是当刚刚被渲染开始的时候,该会处于对应的内容的顶部,然后开始滑动的时候,该会跑到屏幕的顶端。直到滑动到下一个section的header(头)视图,然后被替代为止。

    renderSeparator  (sectionID,rowID,adjacentRowHighlighted)=>renderable

    如果设置该方法,会在被每一行的下面渲染一个组件作为分隔。除了每一个section分组的头部视图前面的最后一行。

    方法

    getMetrics()

    导出一些用于性能分析的数据。

    scrollTo

    滚动到指定的X,Y偏移处,可以指定是否加上过渡动画。

    二、ListView高级特性

    2.1给每段/组数据天天以后带有粘性的头部。

    2.2在列表头部和尾部增加单独的内容,在到达列表尾部的时候调用函数(onEndReached),还有在视野可见的数据变化时调用回调函数(onChangeVisibleRows)。

    2.3在性能方面优化

    只更新变化的行 - 提供给数据源的rowHasChanged函数可以告诉ListView中它是否需要重绘一行数据(即:数据是否发生了变化)参见ListViewDataSource

    限制频率的行渲染-默认情况下,每次消息循环只有一行会被渲染(用可以pageSize属性配置)这把较大的工作分散成小的碎片,以降低因为渲染而导致丢帧的可能性。

    三、ListView常用Demo

    3.1简单的电商demo


    3.1.1listView的使用步骤:

    代码截图:

    运行效果:

    这种比较简单,只要到时候改变返回的row中的View的样式即可

    3.2九宫格demo

    使用ListView实现九宫格的原理就是,一个listView,将cell通过flex布局实现,主轴方向的改变,然后设置,每个cell的布局得到。

    注意:在这个过程中,实现row主轴的改变后,实现多行显示总是不行,原因是removeClippedSubviews={false}的默认状态是ture是隐藏的。

    3.2.1 代码截图:

    运行截图:

    3.3分组带有头视图的demo 

    DataSource 的方法解析及技术分析

    1.数组的提取和更新方法

    clone方法会自动提取新数据并进行逐行对比(使用rowHasChanged方法中的策略),这样ListView就知道哪些行需要重新渲染了。

     cloneWithRows(dataBlob(原始数据), rowIdentities(二维数组))

    cloneWithRowsAndSections(dataBlob(原始数据), sectionIdentities(数组,包含了section标识符), rowIdentities(数组))

    section标题和行数据提供自定义的提取方法和hasChanged比对方法。如果不提供,则会使用默认的defaultGetRowData和defaultGetSectionHeaderData方法来提取行数据和section标题。

    默认的提取函数处理一下的数据类型

    { sectionID_1: { rowID_1: rowData1, ... }, ... }     =>>>   key:{}

    { sectionID_1: [ rowData1, rowData2, ... ], ... }    =>>>   key:[]

    [ [ rowData1, rowData2, ... ], ... ]                  = >>>> [[],[]....]

    通过构造函数提取数组的方法一共有四种:

    (1).getRowData(sectionIndex, rowIndex)    返回渲染行数所需的数据(指定如何从原始dataBlob中提取数据)。

    (2).getSectionHeaderData(dataBlob, sectionID); 获取section标题数据。

    (3)rowHasChanged(prevRowData, nextRowData);  通过对比创建数组

    (4). sectionHeaderHasChanged(prevSectionData, nextSectionData);  通过对比创建

    2.其他方法

    getRowCount()  获取行数

    getRowAndSectionCount()   获取原始数据的分组个数

    rowShouldUpdate(sectionIndex, rowIndex)   返回值表明某行数据是否已变更,需要重新渲染。

    getRowData(sectionIndex, rowIndex)   返回渲染行所需的数据(指定如何从原始dataBlob中提取数据)。

    getSectionIDForFlatIndex(index)    给定索引值,求其对应sectionID。如果查找不到则返回null。

    getSectionLengths()   返回一个数组,包含每个section的行数量。

    sectionHeaderShouldUpdate(sectionIndex)   返回值用于说明section标题是否需要重新渲染。

    看到上边的大家可能还是蒙蒙的,简单的说就说:

    DataBlob就是原始数据就是一个大的字典{

    sectionID1:{},或者[]

    }

    sectionIDs = ['sectionID1',sectionID2',sectionID3'.......] 每组的标题

    rowIDS = [[row1,row2],[row1,row2],[row1,row2],[row1,row2].....]  每组的数据

    第一步需要在datasource中,设置ListView获取row和section方法

    第二步因为需要对数据进行循环拆分,组合成dataBlob需要的数据样式属于耗时操作,放到componentDidMount方法中,完成操作后刷新状态,将数据传到listView的render()方法中。

    第三步,返回相关函数,设置属性样式布局

    代码截图

    运行结果:

    完整demo请https://github.com/nanaLxs/ListView-demo下载。如果感觉可以请star。在这里谢谢啦!!

    相关文章

      网友评论

      • f24bb1a26338:仓库还是空,
        StartBoy:仓库是空的。
        Zax_Smile:@Wolf_Totem好好,有时间整理一下
      • 小小看护:github上面的demo为空的。
        Zax_Smile:@kuangyanboy 明天我会重新上传。这几天比较忙!要是想看明天再看的:smile::smile:
      • Zax_Smile:是吗我看一下的
      • 心至靜行至遠:github上的demo仓库为空的。。。
      • Xcode8:你好我写listView的九宫格的时候,出现(一行占了很大的一个位置,本来是总共的宽度的,一行的cell占用了)
        Zax_Smile:@Xcode8 设置listview 切割多余试图的属性事实,
        Xcode8:@Zax_Smile listViewStyle:{
        width:width,
        //设置横向布局
        flexDirection:'row',
        //设置换行显示
        flexWrap:'wrap',
        },
        iconStyle:{
        width:80,
        height:80,
        },
        cellViewStyle:{
        width:100,
        height:100,
        marginLeft:marginX,
        marginTop:20,
        alignItems:'center'//居中显示
        }
        Zax_Smile:@Xcode8你给每个cell 设置宽度了吗

      本文标题:React Native从入门到深入--组件ListView的使

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