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

  • 相关阅读:
    微信小程序 单选按钮 最佳
    微信小程序 单选按钮的实现
    微信小程序 单选框实现
    Java Code To Create Pyramid and Pattern
    Java language
    npm Err! Unexpected end of JSON input while parsing near
    Node.js Express FrameWork Tutorial
    Higher-Order Function Examples
    Create First HTTP Web Server in Node.js: Complete Tutorial
    Node.js NPM Tutorial: Create, Publish, Extend & Manage
  • 原文地址:https://www.cnblogs.com/shaoting/p/7069312.html
Copyright © 2011-2022 走看看