React-Native新列表组件FlatList和SectionList学习 | | 联动列表实现
React-Native在0.43推出了两款新的列表组件:FlatList(高性能的简单列表组件)和SectionList(高性能的分组列表组件).
从官方上它们都支持常用的以下功能:
- 完全跨平台。
- 支持水平布局模式。
- 行组件显示或隐藏时可配置回调事件。
- 支持单独的头部组件。
- 支持单独的尾部组件。
- 支持自定义行间分隔线。
- 支持下拉刷新。
- 支持上拉加载。
其中,SectionList适合分组/类/区,但是在0.43版本中,如果希望section的头部能够吸顶悬浮,请暂时先使用老版的<ListView>.
它们都是基于<VirtualizedList>
组件的封装(不同于ListView,ListView是继承自ScrollView,这意味着ListView可以使用所有ScrollView的属性,但是不带重用,性能稍微不足,也就是说FlatList.SectionList这两款组件和ListView,ScrollView没啥关系,而ListView和ScrollView是父子关系),.所以需要注意几点.详细的请在官方浏览.其中有一点必须注意:在使用时,默认情况下每行都需要提供一个不重复的key属性.也可以提供一个keyExtractor
函数来动态绑定数据源中的id等其他不唯一的数据。如果不绑定会报一个警告:
接下里使用这两个组件写一个demo:列表组件的联动(ps:其实个人感觉使用ListView实现更加方便.也更易扩展)
数据源我们采用本地数据:
{
"food_spu_tags":[ {
"title":"1",
"data":[
{
"name":"一 nghnh",
"key":"1"
},
{
"name":"一 tyui22uyt",
"key":"2"
},
{
"name":"一 3fdsfdga",
"key":"3"
}
]
},
{
"title":"2",
"data":[
{
"name":"二 fsd",
"key":"4"
},
{
"name":"二 gfdh",
"key":"5"
},
{
"name":"二 ghdsfd",
"key":"6"
},
{
"name":"二 hkjhg",
"key":"7"
},
{
"name":"二 oiuytre",
"key":"8"
},
{
"name":"二 phfd",
"key":"9"
}
]
},
{
"title":"3",
"data":[
{
"name":"三 pknbv",
"key":"10"
},
{
"name":"三 qazxsef",
"key":"11"
},
{
"name":"三 plmnbgf",
"key":"12"
},
{
"name":"三 ggggg",
"key":"13"
},
{
"name":"三 gfd",
"key":"14"
},
{
"name":"三 fgh",
"key":"15"
},
{
"name":"三 hhf",
"key":"16"
},
{
"name":"三 jff",
"key":"17"
},
{
"name":"三 sfgd",
"key":"18"
},
{
"name":"三 dffhsd",
"key":"19"
},
{
"name":"三 ghd",
"key":"20"
},
{
"name":"三 ghsg",
"key":"21"
}
]
},
{
"title":"4",
"data":[
{
"name":"四 ghs",
"key":"22"
},
{
"name":"四 hth",
"key":"23"
}
]
},
{
"title":"5",
"data":[
{
"name":"五 teh",
"key":"24"
},
{
"name":"五 thtr",
"key":"25"
},
{
"name":"五 thereth",
"key":"26"
},
{
"name":"五 yefdgs",
"key":"27"
},
{
"name":"五 htweh",
"key":"28"
},
{
"name":"五 thrhwt",
"key":"29"
},
{
"name":"五 geheht",
"key":"30"
},
{
"name":"五 thwtw",
"key":"31"
}
]
},
{
"title":"6",
"data":[
{
"name":"六 thsfsg",
"key":"32"
},
{
"name":"六 thwfs",
"key":"33"
},
{
"name":"六 htsfd",
"key":"34"
}
]
},
{
"title":"7",
"data":[
{
"name":"七 hgshfd",
"key":"35"
}
]
},
{
"title":"8",
"data":[
{
"name":"八 rgdsgsfd",
"key":"36"
},
{
"name":"八 grht",
"key":"37"
},
{
"name":"八 htrfss",
"key":"38"
},
{
"name":"八 thsgfd",
"key":"39"
},
{
"name":"八 hthe",
"key":"40"
},
{
"name":"八 trgtsf",
"key":"41"
},
{
"name":"八 f45f",
"key":"42"
},
{
"name":"八 4qtq",
"key":"43"
},
{
"name":"八 43f",
"key":"44"
},
{
"name":"八 43ff",
"key":"45"
},
{
"name":"八 45gwrsfd",
"key":"46"
}
]
},
{
"title":"9",
"data":[
{
"name":"九 43qgf",
"key":"47"
},
{
"name":"九 ref3",
"key":"48"
},
{
"name":"九 54sf",
"key":"49"
}
]
},
{
"title":"10",
"data":[
{
"name":"十 43refsd",
"key":"50"
},
{
"name":"十 43refzd",
"key":"51"
},
{
"name":"十 4q3gfd",
"key":"52"
},
{
"name":"十 wgf",
"key":"53"
},
{
"name":"十 4q3fs",
"key":"54"
}
]
},
{
"title":"11",
"data":[
{
"name":"十一 wrf",
"key":"55"
},
{
"name":"十一 5ersf",
"key":"56"
},
{
"name":"十一 43fs",
"key":"57"
},
{
"name":"十一 43fs",
"key":"58"
},
{
"name":"十一 5gs",
"key":"59"
},
{
"name":"十一 w5gfsd",
"key":"60"
},
{
"name":"十一 4qrgfs",
"key":"61"
}
]
},
{
"title":"12",
"data":[
{
"name":"十二 4wgfsd",
"key":"62"
},
{
"name":"十二 w5gfsd",
"key":"63"
},
{
"name":"十二 4qgfsgf",
"key":"64"
},
{
"name":"十二 3qgsf",
"key":"65"
}
]
}
]
}
1.新建个主类放置左右两个列表组件(左边的FlatList右边的SectionList)
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/ import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import LeftFlatList from './leftFlatList'
import RightSectionList from './RightSectionList'
import linkageData from './linkage.json'
export default class Main extends Component {
render() {
return (
<View style={{flexDirection:'row'}}>
<LeftFlatList data = {linkageData}/>
<RightSectionList data = {linkageData}/>
</View>
);
}
} const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
2.左边的FlatList,key采用keyExtractor函数绑定,就是数据源中title.
/**
* Created by shaotingzhou on 2017/6/22.
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
Platform,
Dimensions,
RefreshControl,
FlatList,
ActivityIndicator,
DeviceEventEmitter,
ScrollView
} from 'react-native';
var {width,height} = Dimensions.get('window');
var dataAry = [] export default class LeftFlatList extends Component{
// 构造
constructor(props) {
super(props);
dataAry = this.props.data.food_spu_tags
this.state = {
dataAry: dataAry,
cell:0 //默认选中第一行
};
}
render() {
return (
<FlatList
ref='FlatList'
style={{width:80}}
data = {this.state.dataAry} //数据源
renderItem = {(item) => this.renderRow(item)} //每一行render
ItemSeparatorComponent = {()=>{return(<View style={{height:1,backgroundColor:'cyan'}}/>)}} //分隔线
keyExtractor={this.keyExtractor} //使用json中的title动态绑定key
/>
);
}
//使用json中的title动态绑定key
keyExtractor(item: Object, index: number) {
return item.title
}
//每一行render
renderRow =(item) =>{
return(
<TouchableOpacity onPress={()=>this.cellAction(item)}>
<View style={{height:60,flexDirection:'row',alignItems:'center'}}>
<View style={{height:50,width:5,backgroundColor: item.index == this.state.cell ? 'red' : 'rgba(0,0,0,0)'}}/>
<Text style={{marginLeft:20}}>{item.item.title}</Text>
</View>
</TouchableOpacity>
)
}
//点击某行
cellAction =(item)=>{
// alert(item.index)
if(item.index < this.state.dataAry.length - 1){
this.setState({
cell:item.index
})
DeviceEventEmitter.emit('left',item.index); //发监听
} } componentWillUnmount(){
// 移除监听
this.listener.remove();
} componentWillMount() {
this.listener = DeviceEventEmitter.addListener('right',(e)=>{
this.refs.FlatList.scrollToIndex({animated: true, index: e-1})
this.setState({
cell:e-1
})
});
} }; var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
}
});
3.右边的SectionList,key采用数据源中id来绑定.
/**
* Created by shaotingzhou on 2017/6/22.
*/
import React, {Component} from 'react';
import {
StyleSheet,
View,
Text,
SectionList,
Dimensions,
DeviceEventEmitter,
ScrollView
} from 'react-native';
var {width,height} = Dimensions.get('window');
var sectionData = []
export default class RightSectionList extends Component {
// 构造
constructor(props) {
super(props);
sectionData = this.props.data.food_spu_tags
this.state = {
sectionData:sectionData
};
}
//行
renderItem = (item) => {
return (
<View style={{height:60,justifyContent:'center',marginLeft:15}}>
<Text>{item.item.name}</Text>
</View>
)
}
//头
sectionComp = (section) => {
return (
<View style={{height:30,backgroundColor:'#DEDEDE',justifyContent:'center',alignItems:'center'}}>
<Text >{section.section.title}</Text>
</View>
)
} render() {
return (
<SectionList
ref='sectionList'
style={{width:width-80}}
renderSectionHeader={(section)=>this.sectionComp(section)} //头
renderItem={(item)=>this.renderItem(item)} //行
ItemSeparatorComponent = {()=>{return(<View style={{height:1,backgroundColor:'black'}}/>)}}//分隔线
sections={this.state.sectionData} //数据
onViewableItemsChanged = {(info)=>this.itemChange(info)} //滑动时调用
/> );
} componentDidMount() {
//收到监听
this.listener = DeviceEventEmitter.addListener('left',(e)=>{
// console.log(e + 1) // 左边点击了第几行
// console.log(sectionData) // 数据源
// console.log(sectionData[e])
// console.log(sectionData[e].data.length)
// SectionList实现scrollToIndex需要修改VirtualizedSectionList和SectionList源码
if(e > 0){
//计算出前面有几行
var count = 0
for(var i = 0; i < e; i++){
count += sectionData[i].data.length +1
}
this.refs.sectionList.scrollToIndex({animated: true, index: count})
}else {
this.refs.sectionList.scrollToIndex({animated: true, index: 0}) //如果左边点击第一行,右边则回到第一行
} });
} componentWillUnmount(){
// 移除监听
this.listener.remove();
} itemChange = (info)=>{
let title = info.viewableItems[0].item.title
var reg = new RegExp("^[0-9]*$");
if (reg.test(title)) {
DeviceEventEmitter.emit('right',title); //发监听
}
} }
其中,使用事件监听来实现点击和滑动的监听.
我们使用scrollToIndex来移动.但是呢,FlatList对VirtualizedList封装的时候有添加这个方法,而SectionList并没有(why?).无奈自己修改下它的源码.
a.在node_modules/react-native/Libraries/Lists/SectionList.js 下修改 250-310行代码为
class SectionList<SectionT: SectionBase<any>>
extends React.PureComponent<DefaultProps, Props<SectionT>, void> {
props: Props<SectionT>;
static defaultProps: DefaultProps = defaultProps; render() {
const List = this.props.legacyImplementation ? MetroListView : VirtualizedSectionList;
return <List
ref={this._captureRef}
{...this.props} />;
} _captureRef = (ref) => {
this._listRef = ref;
}; scrollToIndex = (params: { animated?: ?boolean, index: number, viewPosition?: number }) => {
this._listRef.scrollToIndex(params);
}
}
b.在node_modules/react-native/Libraries/Lists/VirtualizedSectionList.js 下的335下面增加
scrollToIndex = (params: { animated?: ?boolean, index: number, viewPosition?: number }) => {
this._listRef.scrollToIndex(params);
}
修改后完整源码见:SectionList.js VirtualizedSectionList.js.
OK.修改完成后就可以实现点击左联右了.
而右联左,通过SectionList的onViewableItemsChanged属性实现.
以后就是关于FlatList和SectionList的学习demo.
再说一遍,实现联动组件最好使用ListView.因为现阶段官方推出的FlatList和SectionList的方法较少,bug较多.
demo源码github:https://github.com/pheromone/RN-FlatList-SectionList
React-Native新列表组件FlatList和SectionList学习 | | 联动列表实现的更多相关文章
- React Native之获取通讯录信息并实现类通讯录列表(ios android)
React Native之获取通讯录信息并实现类通讯录列表(ios android) 一,需求分析 1,获取通讯录信息,筛选出通讯录里有多少好友在使用某个应用. 2,获取通讯录信息,实现类通讯录,可拨 ...
- react native之组织组件
这些组件包括<TabView>,<NavigatorView>和<ListView>,他们实现了手机端最常用的交互和导航.你会发现这些组件在实际的项目中会非常有用. ...
- React Native之倒计时组件的实现(ios android)
React Native之倒计时组件的实现(ios android) 一,需求分析 1,app需实现类似于淘宝的活动倒计时,并在倒计时结束时,活动也结束. 2,实现订单倒计时,并在倒计时结束时,订单关 ...
- React Native知识6-NavigatorIOS组件
NavigatorIOS包装了UIKit的导航功能,可以使用左划功能来返回到上一界面.本组件并非由Facebook官方开发组维护.这一组件的开发完全由社区主导.如果纯js的方案能够满足你的需求的话,那 ...
- React Native常用第三方组件汇总--史上最全 之一
React Native 项目常用第三方组件汇总: react-native-animatable 动画 react-native-carousel 轮播 react-native-countdown ...
- React Native常用第三方组件汇总--史上最全[转]
本文出处: http://blog.csdn.net/chichengjunma/article/details/52920137 React Native 项目常用第三方组件汇总: react-na ...
- 从零学React Native之12 组件的生命周期
一个React Native组件从它被加载,到最终被卸载会经历一个完整的生命周期.所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解生命周期,是合理开发的关键. ES6语法和之前的ES5 ...
- React Native知识2-Text组件
Text用于显示文本的React组件,并且它也支持嵌套.样式,以及触摸处理.在下面的例子里,嵌套的标题和正文文字会继承来自styles.baseText的fontFamily字体样式,不过标题上还附加 ...
- react native 之子组件和父组件之间的通信
react native开发中,为了封装性经常需要自定义组件,这样就会出现父组件和子组件,那么怎么在父组件和子组件之间相互通信呢,也就是怎么在各自界面push和pop.传值. 父组件传递给子组件: 父 ...
随机推荐
- 一致性hash的实现
原文:https://blog.csdn.net/u011305680/article/details/79721030 1.不带虚拟节点的 package hash; import java.uti ...
- sed 正则的一个小问题
有一段类似以下的文本 aabbccc test[3307]112323553-66778tp aooppx69tp ooppsg aabbccc test[3307]1127233-6674tp bo ...
- activiti5/6 系列之--BpmnModel使用
BpmnModel对象,是activiti动态部署中很重要的一个对象,如果BpmnModel对象不能深入的理解,那可能如果自己需要开发一套流程设计器,使用bpmn-js使用前端或者C/S展现流程流转而 ...
- 【2.0】SpringBoot2配置Druid数据源及监控
什么是Druid? Druid首先是Java语言中最好的数据库连接池,也是阿里巴巴的开源项目.Druid是阿里巴巴开发的号称为监控而生的数据库连接池,在功能.性能.扩展性方面,都超过其他数据库连接池, ...
- 如何用 python 优雅地完成数据库课设
0 前言 偶然间发现 Google 收录了学校实验打卡系统的接口,正好要做数据库课设,便拿来作为 environment. 机房居然装了 python ,早就听说 python 写爬虫速度一流,课上的 ...
- git在本地回退
参考https://www.cnblogs.com/qufanblog/p/7606105.html 已经用 git commit 提交了代码. 可以使用 git reset --hard HEAD ...
- Angular2 EventEmitter
可能你对EventEmitter还不太熟悉,不过别担心,它并不难.EventEmitter只是一个帮你实现观察者模式①的对象.也就是说,它是一个管理一系列订阅者并向其发布事件的对象.就是这么简单.来看 ...
- 2019ExcelVBA一些自己掉进过的坑
1.公式手动重算问题 为避免代码执行过程中引发公式自动重算,拖慢运行速度,在代码中设置了公式手动重算,并计划在代码执行结束前恢复.如果在代码执行过程中捕获错误就直接退出,而没有执行到恢复公式自动重算, ...
- hdu-4856 Tunnels 状压DP
http://acm.hdu.edu.cn/showproblem.php?pid=4856 有若干管道,每个管道有且只能走一次,而地图可以随意走. 那么可以先处理每个管道间的最短路(不要考虑借助其他 ...
- jar包安装到本地仓库
mvn install:install-file -Dfile=hm_test.jar -DgroupId=com.TEST -DartifactId=hm_test -Dversion=1.0 -D ...