zoukankan      html  css  js  c++  java
  • 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"
            }
          ]
        }
      ]
    }
    View Code

    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,
        },
    });
    View Code

    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={{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,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,
        }
    });
    View Code

    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-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); //发监听
            }
        }
    
    
    }
    View Code

    其中,使用事件监听来实现点击和滑动的监听.

    我们使用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);
        }
    }
    View Code

    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

  • 相关阅读:
    跨表修改数据|查询修改数据|两表联合修改数据
    .net oracle 连接
    型材优化截取初步代码
    JQuery.getJSON 从aspx页面返回JSON数据 .
    asp.net form验证
    ASP.NET读取纯真IP数据库QQWry.Dat,得到地址名称
    防止PHP木马,应在PHP.INI里禁止的一些函数
    sqlserver2005中的数据库日志收缩
    jquery.pagination.js分页插件的运用
    ASP.NET前台代码绑定后台变量方法总结
  • 原文地址:https://www.cnblogs.com/shaoting/p/7069312.html
Copyright © 2011-2022 走看看