作者 | 京东金融-移动研发部-前端开发工程师
小白初入坑RN,最近刚好在做一个关于ListView两列布局的排版,而ListView使用场景又比较多,所以我把中间学习过程及疑惑写出来,供像我这样的小白参考,希望对大家有所帮助,大神请忽略。
官网说此组件已经过期,不过用法都差不多,顺便贴上FlatList或SectionList的相关链接:
FlatList: https://reactnative.cn/docs/0.51/flatlist.html
SectionList: https://reactnative.cn/docs/0.51/sectionlist.html
关于listView你可能需要了解的知识点:
flex布局和React Native官网,又或者你更喜欢阅读英文文档:
阮一峰Flex 布局教程语法篇:
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
React Native开发环境搭建:
https://reactnative.cn/docs/0.51/getting-started.html#content
ListView:
https://facebook.github.io/react-native/docs/listview.html
一、什么是ListView
ListView - 一个核心组件,用于高效地显示一个可以垂直滚动的变化的数据列表。最基本的使用方式就是创建一个ListView.DataSource数据源,然后给它传递一个普通的数据数组,再使用数据源来实例化一个ListView组件,并且定义它的renderRow回调函数,这个函数会接受数组中的每个数据作为参数,返回一个可渲染的组件(作为listview的每一行)。
作为核心组件,ListView可以说是日常开发最常用的控件之一。适应的场景还是比较多的,比如会话、商品、问题列表等等各种列表均用到了ListView。React-Native的ListView对于原生的支持还是比较不错的,但是和原生的用法略有不同。
二、ListView有哪些优点
1. RN页面一旦超过一屏,屏幕就会滑不动,需要用到ScrollView 。但是当你的数据特别大的时候ScrollView渲染所有的元素,对性能不太好。
而ListView更适于长列表数据,且元素个数可以增删。和ScrollView不同的是,ListView并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。
2. ListView还支持一些高级特性,譬如给每段/组(section)数据添加一个带有粘性的头部(类似iPhone的通讯录,其首字母会在滑动过程中吸附在屏幕上方);在列表头部和尾部增加单独的内容;在到达列表尾部的时候调用回调函数(onEndReached),还有在视野内可见的数据变化时调用回调函数(onChangeVisibleRows),以及一些性能方面的优化。
有一些性能优化使得ListView可以滚动的更加平滑,尤其是在动态加载可能很大(或者概念上无限长的)数据集的时候:
只更新变化的行 - 提供给数据源的rowHasChanged函数可以告诉ListView它是否需要重绘一行数据(即:数据是否发生了变化)参见ListViewDataSource
限制频率的行渲染 - 默认情况下,每次消息循环只有一行会被渲染(可以用pageSize属性配置)。这把较大的工作分散成小的碎片,以降低因为渲染而导致丢帧的可能性。
三、ListView怎么用
这里只举两个关键的,其他的可以参见官网学习下
1. ListView.DataSource数据源,然后给它传递一个普通的数据数组,再使用数据源来实例化一个ListView组件,并且定义它的renderRow回调函数,这个函数会接受数组中的每个数据作为参数,返回一个可渲染的组件(作为listview的每一行)。
2. rowHasChanged函数也是ListView的必需属性。这里我们只是简单的比较两行数据是否是同一个数据(===符号只比较基本类型数据的值,和引用类型的地址)来判断某行数据是否变化了。
来一个小demo理解下:
上面的例子创建了一个简单的ListView,并预设了一些模拟数据。首先是初始化ListView所需的dataSource,其中的每一项(行)数据之后都在renderRow中被渲染成了Text组件,最后构成整个ListView。
四、ListView 基本布局
五、ListView 九宫格布局实现
九宫格和我们两列布局的布局有点像,所以我直接把上面view宽度直接改了一下就成了我们想要的布局。
但是现在两列布局有一个问题就是当手机的的分辨率大小不同时,两列之间的间隔也会随之变大或者变小。而我现在想让就是两列之间及周围所有的间隔始终是10px,该怎么实现呢?
每个view随着屏幕大小自适应。这个时候view宽度是不能固定的,首先想到flex:1可以实现自适应,但是现在问题又来了,就是我们知道实际开发我们的数据一条一条循环出来。当样式为flex:1时当前循环出来的view会充满整个屏幕。而并非最初期望的两列布局。现在有个思路可以试试:就是把现在Y[n】转化成Y[n][2]的数组然后循环出来,现在我们来模拟一下数据测试下哈:
核心的代码块
当数组长度奇数会遇到上面的问题,最后一个view不是我看我们想要结果,这个时候加个判断就可以,当数组长度为奇数时数组在push一个,然后再把这个补位view设置为透明就可以了。如图:
贴上代码
如果大家有什么问题欢迎留言一起探讨下,另感谢team所有优秀的小伙伴在工作中的帮助及耐心的指导!!
参考资源:
React-Native 之 ListView使用
https://www.jianshu.com/p/2b5ba41f0170
阮一峰Flex 布局教程语法篇:
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
React Native 中文网:
https://reactnative.cn/