React Native常用组件之ListView组件
学习iOS开发的同学应该都知道UITableView,几乎每个APP中都有它的存在,而且衍生出各种形态;那么同样,ListView就是在React Native中的tableView,而且更加简单和灵活易用;让我们一起搞定它。
一、前言
ListView组件是React Native中一个比较核心的组件,用途非常的广; 该组件设计用来高效的展示垂直滚动的数据列表:
1.1 首先创建一个ListView.DataSource数据源,然后给它传递一个普通的数据数组;
1.2 使用数据源(data source)实例化一个ListView组件,定义一个renderRow回调函数,这个函数会接受数组中的每个数据作为参数,并返回一个可渲染的组件(该就是列表的每一行的item)。
二、ListView常用的属性
ScrollView 相关属性样式全部继承
dataSource ListViewDataSource 设置ListView的数据源
initialListSize number
设置ListView组件刚刚加载的时候渲染的列表行数,用这个属性确定首屏或者首页加载的数量,而不是花大量的时间渲染加载很多页面数据,提高性能。
onChangeVisibleRows function
(visibleRows,changedRows)=>void。
当可见的行发生变化的时候回调该方法。
onEndReachedThreshold number
当偏移量达到设置的临界值调用onEndReached
onEndReached function
当所有的数据项行被渲染之后,并且列表往下进行滚动。一直滚动到距离底部onEndReachedThredshold设置的值进行回调该方法。原生的滚动事件进行传递(通过参数的形式)。
pageSize number 每一次事件的循环渲染的行数
removeClippedSubviews bool
该属性用于提供大数据列表的滚动性能。该使用的时候需要给每一行(row)的布局添加over:'hidden'样式。该属性默认是开启状态。
renderFooter function 方法 ()=>renderable
在每次渲染过程中头和尾总会重新进行渲染。如果发现该重新绘制的性能开销比较大的时候,可以使用StaticContainer容器或者其他合适的组件。
renderHeader function 方法
在每一次渲染过程中Footer(尾)该会一直在列表的底部,header(头)该会一直在列表的头部,用法同上。
renderRow function (rowData,sectionID,rowID,highlightRow)=>renderable
该方法有四个参数,其中分别为数据源中一条数据,分组的ID,行的ID,以及标记是否是高亮选中的状态信息。
renderScrollComponent function
方法 (props)=>renderable 该方法可以返回一个可以滚动的组件。默认该会返回一个ScrollView
renderSectionHeader function (sectionData,sectionID)=>renderable
如果设置了该方法,这样会为每一个section渲染一个粘性的header视图。该视图粘性的效果是当刚刚被渲染开始的时候,该会处于对应的内容的顶部,然后开始滑动的时候,该会跑到屏幕的顶端。直到滑动到下一个section的header(头)视图,然后被替代为止。
renderSeparator function
(sectionID,rowID,adjacentRowHighlighted)=>renderable
如果设置该方法,会在被每一行的下面渲染一个组件作为分隔。除了每一个section分组的头部视图前面的最后一行。
scrollRenderAheadDistance number
进行设置当该行进入屏幕多少像素以内之后就开始渲染该行
三、ListView的高阶特性
ListView同样支持一些高级特性,包括设置每一组的粘性的头部(类似于iPhone)、支持设置列表的header以及footer视图、当数据列表滑动到最底部的时候支持onEndReached方法回调、设备屏幕列表可见的视图数据发生变化的时候回调onChangeVisibleRows以及一些性能方面的优化特性。
ListView设计的时候,当需要动态加载非常大的数据的时候,下面有一些方法性能优化的方法可以让我们的ListView滚动的时候更加平滑:
(1)只更新渲染数据变化的那一行 ,rowHasChanged方法会告诉ListView组件是否需要重新渲染当前那一行。
(2)选择渲染的频率,默认情况下面每一个event-loop(事件循环)只会渲染一行(可以同pageSize自定义属性设置)。这样可以把大的工作量进行分隔,提供整体渲染的性能。
四、综合大演练
4.1 ListView练习,代码如下:
/*** Sample React Native App* https://github.com/facebook/react-native* @flow*/import React, { Component } from 'react'; import {AppRegistry,StyleSheet,Text,View,ListView,Image,TouchableOpacity } from 'react-native'; var Wine = require('./Wine.json'); var Dimensions = require('Dimensions'); var {width} = Dimensions.get('window'); export default class FListViewDemo1 extends Component{constructor(props){super(props);var ds = new ListView.DataSource({rowHasChanged:(r1,r2) => r1 !== r2});this.state = {dataSource:ds.cloneWithRows(Wine)};}render(){return(<ListViewstyle = {{backgroundColor:'white'}}dataSource = {this.state.dataSource}renderRow = {this.renderRow}/> );}renderRow(rowData,sectionID,rowID,highlightRow){return(<TouchableOpacity activeOpacity={0.4}><View style={styles.cellViewStyle}><Image source={{uri:rowData.image}} style={styles.leftImageStyle}/><View style = {styles.rightViewStyle}><Text style={styles.topTitleStyle}>{rowData.name}</Text><Text style={styles.bottomTitleStyle}>¥{rowData.money}</Text></View></View></TouchableOpacity> );} }const styles = StyleSheet.create({cellViewStyle:{padding:10,backgroundColor:'white',borderBottomWidth:0.3,borderBottomColor:'#e8e8e8',flexDirection:'row'},leftImageStyle:{width:60,height:60,marginRight:10,justifyContent:'center'},topTitleStyle:{color:'red',fontSize:15,width:width * 0.8,marginBottom:10},bottomTitleStyle:{},rightViewStyle:{} });
4.2 带有组头的汽车品牌展示
核心代码:
完整代码:
/*** Sample React Native App* https://github.com/facebook/react-native* @flow*/import React, { Component } from 'react'; import {AppRegistry,StyleSheet,Text,View,ListView,Image,TouchableOpacity } from 'react-native';var Car = require('./Car.json');export default class FListViewDemo1 extends Component{constructor(props){super(props);var getSectionData = (dataBlob,sectinID) =>{return dataBlob[sectinID];}var getRowData = (dataBlob,sectinID,rowID) =>{return dataBlob[sectinID + ':' + rowID];}this.state = {dataSource:new ListView.DataSource({getSectionData:getSectionData,//获取组中数据getRowData:getRowData,//获取行中数据rowHasChanged:(r1,r2) => r1 !== r2,sectionHeaderHasChanged:(s1,s2) => s1 !== s2})};}render(){return(<View style = {styles.outerViewStyle}><View style={styles.headerViewStyle}><Text>SeeMyGo品牌</Text></View><ListViewdataSource={this.state.dataSource}renderRow={this.renderRow}renderSectionHeader={this.renderSectionHeader}style ={{backgroundColor:'white'}}/></View> );}renderRow(rowData){return(<TouchableOpacity actionOpacity ={0.5}><View style={styles.rowStyle}><Image source={{uri:rowData.icon}} style={styles.rowImageStyle}/><Text>{rowData.name}</Text></View></TouchableOpacity> );}renderSectionHeader(sectinData,sectionID){return(<View style={styles.sectionHeaderViewStyle}><Text>{sectinData}</Text></View> );}componentDidMount(){//调用Json数据this.loadDataFromJson();}loadDataFromJson(){//拿到json数据var jsonData = Car.data;//定义一下变量var dataBlob = {},sectionIDs = [],rowIDs = [],cars = [];//遍历for(var i = 0;i<jsonData.length;i++){//1.把组号放入sectionID数组中 sectionIDs.push(i);//2.把组中的内容放入dataBlob中dataBlob[i] = jsonData[i].title;//3.取出该组中所有的车cars = jsonData[i].cars;//4.遍历所有的测数组rowIDs[i] = [];for(var j = 0;j<cars.length;j++){//把行号放入rowIDs rowIDs[i].push(j);//把每一行中的内容放入dataBlob对象中dataBlob[i+':'+j] = cars[j];}}//更新状态this.setState({dataSource:this.state.dataSource.cloneWithRowsAndSections(dataBlob,sectionIDs,rowIDs)});} }const styles = StyleSheet.create({outerViewStyle:{flex:1},headerViewStyle:{height:64,backgroundColor:'orange',justifyContent:'center',alignItems:'center'},rowStyle:{flexDirection:'row',alignItems:'center',padding:10,borderBottomColor:'#e8e8e8',borderBottomWidth:0.3},rowImageStyle:{width:70,height:70},sectionHeaderViewStyle:{backgroundColor:'#e8e8e8',height:25,justifyContent:'center'} });
View Code
运行结果:
项目技术点分析:
在React Native中,ScrollView组件可以使用 stickyHeaderIndices
轻松实现 sticky
效果;而使用ListView组件时,使用 stickyHeaderIndices
则不生效。
如何实现滚动时每个section header会吸顶?
在ListView中要实现 sticky
,需要使用 cloneWithRowsAndSections
方法,将 dataBlob
(object), sectionIDs
(array), rowIDs
(array) 三个值传进去。
dataBlob
dataBlob
包含ListView所需的所有数据(section header 和 rows),在ListView渲染数据时,使用getSectionData
和getRowData
来渲染每一行数据。dataBlob
的key
值包含sectionID
+rowId
sectionIDs
sectionIDs
用于标识每组section。
rowIDs
rowIDs
用于描述每个section
里的每行数据的位置及是否需要渲染。在ListView渲染时,会先遍历rowIDs
获取到对应的dataBlob
数据。
模拟对应的数据结构
在 DataSource
中,设置ListView获取row和section的方法
最后
1. 刷新状态,将数据传入到listView中:
this.setState({dataSource:this.state.dataSource.cloneWithRowsAndSections(dataBlob,sectionIDs, rowIDs) });
2. 设置listView的相关属性:
<ListViewdataSource = {this.state.dataSource}renderRow = {this.renderRow}renderSectionHeader = {this.renderSectionHeader}/>
4.3 用ListView实现九宫格布局
相关技术点:
通常情况下,我们对ListView的操作是纵向的,如果是横向的,则需要设置ListView的contentContainerStyle属性,添加flexDirection:‘row’让多个ListView在同一行显示,而且通过flexWrap:'wrap'进行换行。
核心代码:
完整代码:
/*** Sample React Native App* https://github.com/facebook/react-native* @flow*/import React, { Component } from 'react'; import {AppRegistry,StyleSheet,Text,View,ListView,Image,TouchableOpacity, // 不透明度触摸 AlertIOS } from 'react-native';var Dimensions = require('Dimensions'); var screenWidth = Dimensions.get('window').width;// 导入json数据 var shareData = require('./shareData.json');// 一些常量设置 var cols = 3; var cellWH = 100; var vMargin = (screenWidth - cellWH * cols) / (cols + 1); var hMargin = 25;// ES5 var AListViewDemo = React.createClass({// 设置默认值,固定值() getDefaultProps(){return{}},// 设置一些初始值(可以变化) getInitialState(){// 创建数据源var ds = new ListView.DataSource({rowHasChanged:(r1, r2) => r1 !== r2});return{dataSource: ds.cloneWithRows(shareData.data)}},render(){return(<ListViewdataSource={this.state.dataSource}renderRow={this.renderRow}contentContainerStyle={styles.listViewStyle}/> );},// 单独的cell renderRow(rowData){return(<TouchableOpacity activeOpacity={0.5} onPress={()=>{AlertIOS.alert('哈哈')}}><View style={styles.innerViewStyle}><Image source={{uri: rowData.icon}} style={styles.iconStyle}/><Text>{rowData.title}</Text></View></TouchableOpacity> );}});const styles = StyleSheet.create({listViewStyle:{// 改变主轴的方向flexDirection:'row',// 多行显示flexWrap:'wrap'},iconStyle:{width:80,height:80},innerViewStyle:{width:cellWH,height:cellWH,marginLeft:vMargin,marginTop:hMargin,// 居中alignItems:'center'} });AppRegistry.registerComponent('AListViewDemo', () => AListViewDemo);
View Code
运行效果:
4.4 自定义Cell
相关技术点:
在实际开发中,ListView会有多种样式,那么这里面就需要我们自己自定义cell来完成各种界面布局需求。
核心代码:
4.5 ListView中多界面传参
相关技术点:
1. 关联界面数据顺传和逆传;
2. 采用通知实现非关联界面数据传递;
3. 购物车逻辑处理;
4. 处理RN中对象深浅拷贝。
核心代码:
案例截图:
转载于:https://www.cnblogs.com/xjf125/p/10387862.html
React Native常用组件之ListView组件相关推荐
- React Native使用指南-原生UI组件
在如今的App中,已经有成千上万的原生UI部件了--其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多.React Native已经封装了大部分最常见的组件,譬如Scr ...
- React Native常用组件之ListView
1. ListView常用属性 ScrollView 相关属性样式全部继承 dataSource ListViewDataSource 设置ListView的数据源 initialListSize n ...
- React Native FlatList和SectionList列表组件
FlatList 之前使用的组件是ListView,当时要添加一个下拉刷新,上拉加载的功能,所以对ListView做了一些封装,但是后来看官方文档,不建议再使用ListView,因为效率问题,做过An ...
- 如何在React Native中使用文本输入组件?
You know, an app becomes more authentic and professional when there is the interaction between the a ...
- 【React Native开发】React Native控件之RefreshControl组件具体解释(21)
转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50672747 本文出自:[江清清的博客] (一)前言 [好消息]个人 ...
- native react 折线图_【详解】纯 React Native 代码自定义折线图组件(译)
本文为 Marno 翻译,转载必须保留出处! 公众号[ Marno ],关注后回复 RN 加入交流群 React Native 优秀开源项目大全:http://www.marno.cn 一.前言 在移 ...
- 【React Native开发】React Native控件之TextInput组件讲解与QQ登录界面实现(11)
转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50589570 本文出自:[江清清的博客] (一)前言 [好消息]个人 ...
- React Native常用第三方汇总
React Native 项目常用第三方组件汇总: react-native-animatable 动画 react-navigation github : https://reactnavig ...
- React Native常用第三方组件汇总【建议收藏】
react-native-system-setting 修改系统设置 react-native-picker-select 数据选择 react-native-searchable-dropdown ...
- android 高德地图 3d,在React Native中使用 高德地图组件react-native-amap3d
react-native 高德地图组件,使用最新 3D SDK,支持 Android + iOS,受react-native-maps启发,提供功能丰富且易用的接口. node 主要功能:react ...
最新文章
- oracle11g insufficient,ORACLE11GORA-01031:insufficientprivileges
- 哪些是能安装mysql的文件_安装mysql详细步骤有哪些?
- fuzz系列之libfuzzer
- mybatis下log4j使用
- olap mysql_MySQL与OLAP:分析型SQL查询最佳实践探索
- pip is configured with locations that require TLS/SSL, however the ssl module in Python is not avail
- 面试官让我用channel实现sync包里的同步锁,是不是故意为难我?
- matlab fft freqz,【急】请教 fft、freqz、bode 求相频响应的区别及原因
- 利用scrapy爬取美图录网站图集按模特姓名存储到本地(三)
- 包过滤型防火墙iptables
- 忍者安全渗透系统(NINJITSU OS V3)的安装详细过程,亲测新旧vm版本都可安装,附带下载来源
- 商品库存盘点 门店和仓库 需要盘点的物品都可以使用 多种方式设备可以盘点商品库存 移动智能终端盘点机盘点
- php sapi 那些坑,安装PHP出现make: *** [sapi/cli/php] Error 1 解决办法
- WPA2/WPA3混合与WPA3的hostapd配置区别
- 一文搞懂广播电视节目制作经营许可证办理流程
- apdl与传统计算机语言,ANSYS经典APDL语言详解及ANSYS二次开发
- arduino 天下第一(暴论) -- 智能猫眼与 SDDC 连接器移植到 arduino 上
- MySQL数据库学习笔记(10)- distinct与in和exists子查询
- 《redis设计与实现》
- 华为RPA WeAutomate Studio使用心得
热门文章
- 从零实现深度学习框架——优化反向传播相关代码
- 每周荐书:微服务、SQL调优、机器学习(评论送书)
- 优化理论05----最速下降法、最速下降法思想、python实现
- 25 矩阵——QR分解、Householder 矩阵、镜面反射
- Tensorflow:模型保存和服务
- 6个座位办公室最佳位置_6个办公室座位的最佳位置 六个最好的办公室座位位置...
- 小蠓虫如何灭_怎样消灭蠓虫?
- mysql从一个表查询插入另一个表存在时更新_漫谈MySQL的锁机制
- React [Umi] history(API) 路由监听
- L1-1 PTA使我精神焕发 (5 分)