React-Native新列表组件FlatList和SectionList学习 | | 联动列表实现

时间:2022-06-30 12:05:20

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等其他不唯一的数据。如果不绑定会报一个警告:

React-Native新列表组件FlatList和SectionList学习 | | 联动列表实现

接下里使用这两个组件写一个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较多.

React-Native新列表组件FlatList和SectionList学习 | | 联动列表实现

demo源码github:https://github.com/pheromone/RN-FlatList-SectionList

React-Native新列表组件FlatList和SectionList学习 | | 联动列表实现的更多相关文章

  1. React Native之获取通讯录信息并实现类通讯录列表&lpar;ios android&rpar;

    React Native之获取通讯录信息并实现类通讯录列表(ios android) 一,需求分析 1,获取通讯录信息,筛选出通讯录里有多少好友在使用某个应用. 2,获取通讯录信息,实现类通讯录,可拨 ...

  2. react native之组织组件

    这些组件包括<TabView>,<NavigatorView>和<ListView>,他们实现了手机端最常用的交互和导航.你会发现这些组件在实际的项目中会非常有用. ...

  3. React Native之倒计时组件的实现&lpar;ios android&rpar;

    React Native之倒计时组件的实现(ios android) 一,需求分析 1,app需实现类似于淘宝的活动倒计时,并在倒计时结束时,活动也结束. 2,实现订单倒计时,并在倒计时结束时,订单关 ...

  4. React Native知识6-NavigatorIOS组件

    NavigatorIOS包装了UIKit的导航功能,可以使用左划功能来返回到上一界面.本组件并非由Facebook官方开发组维护.这一组件的开发完全由社区主导.如果纯js的方案能够满足你的需求的话,那 ...

  5. React Native常用第三方组件汇总--史上最全 之一

    React Native 项目常用第三方组件汇总: react-native-animatable 动画 react-native-carousel 轮播 react-native-countdown ...

  6. React Native常用第三方组件汇总--史上最全&lbrack;转&rsqb;

    本文出处: http://blog.csdn.net/chichengjunma/article/details/52920137 React Native 项目常用第三方组件汇总: react-na ...

  7. 从零学React Native之12 组件的生命周期

    一个React Native组件从它被加载,到最终被卸载会经历一个完整的生命周期.所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解生命周期,是合理开发的关键. ES6语法和之前的ES5 ...

  8. React Native知识2-Text组件

    Text用于显示文本的React组件,并且它也支持嵌套.样式,以及触摸处理.在下面的例子里,嵌套的标题和正文文字会继承来自styles.baseText的fontFamily字体样式,不过标题上还附加 ...

  9. react native 之子组件和父组件之间的通信

    react native开发中,为了封装性经常需要自定义组件,这样就会出现父组件和子组件,那么怎么在父组件和子组件之间相互通信呢,也就是怎么在各自界面push和pop.传值. 父组件传递给子组件: 父 ...

随机推荐

  1. CSS基础知识汇总

    前言 原文连接:http://www.cnblogs.com/wanghzh/p/5805678.html 在此基础上又做了大量的扩充 CSS简介 CSS是Cascading Style Sheets ...

  2. Python将数据插入到数据库时遇到单引号插入错误的问题

    这才是真正的解决方法,真不知道有些人连试都没试过就乱转载 比如你要插入一个字符串,是一个变量 如:str = "I'am a handsom boy" 由于这个字符串包含',插入数 ...

  3. (转)java内部类详解

    本文转自http://www.cnblogs.com/dolphin0520/p/3811445.html,谢谢作者 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能 ...

  4. Django快速入门

    Django 是用 Python 写的一个*和开放源码 web 应用程序框架.web框架是一套组件,能帮助你更快.更容易地开发web站点.当你开始构建一个web站点时,你总需要一些相似的组件:处理用 ...

  5. 按Enter登录&comma;Esc退出

    回车登录,下图处,选择登录按钮的方法 下图是按ESC

  6. sac cut

    Put a perl script here in order to remind myself of its correct usage:

  7. java 代理 agency

    java并没有对其提供直接的支持,这是继承和组合的中庸之道,因为我们将一个成员对象置于所要构造的类中(组合),但与此同时我们在新类中暴露了该成员的所有方法(就像继承),使用代理时可以拥有更多的控制力, ...

  8. 006&period;KVM虚机克隆

    一 KVM宿主机内克隆 1.1 查看虚拟机配置 [root@kvm-host ~]# cat /etc/libvirt/qemu/vm01-centos6.8.xml ………… [root@kvm-h ...

  9. django权限管理

    当我们为应用创建一个Models, 在同步到数据库里,django默认给了三个权限 ,就是 add, change, delete权限. 首先,我们创建一个perm_test的project, 然后再 ...

  10. Apereo CAS - 1

    1. download  cas 4.2.2 from https://github.com/apereo/cas/releases 2. eclipse import cas 4.2.2 eclip ...