zoukankan      html  css  js  c++  java
  • ReactNative: 组件封装(如二级菜单组件)

    一、简介

    前面都是介绍关于RN基本的API组件和UI组件,这些组件在复杂的复合组件中都是以颗粒度的形式存在的,如何有效合理的利用它们进行封装,是十分有必要的。开发复合组件的好处有很多,最为明显的就是复用和独立功能模块。复合组件分为两种,一种是静态的,这种组件不具备重用的特征,由静态数据组成,开发静态页面即可,不考虑数据的传递。另一种就是动态组件,它可以通过接收外部传入的动态数据进行联动,达到组件复用的效果。

    二、应用

    动态组件有很多应用,最典型的例如二级菜单组件,样式固定,数据可变,通过一级目录的选择来联动刷新二级目录的数据。思路很简单,首先构建数据模型;其次,对要封装的组件进行粒度拆分,依次按照此粒度构建组件;接着,设定组件的属性接口;然后,设计组件渲染规则并分解渲染, 绑定事件;最后,引用封装的组件并传入数据模型即可。完整示例如下:

    HeadList.js【粒度组件:头部标签】

    import React, { Component } from 'react';
    import {
        StyleSheet,
        View,
        Text,
        TouchableOpacity
    } from 'react-native';
    
    export default class HeadList extends Component{
    
        render(){
    
            let headData = this.props.data;
            let update = this.props.update;
            const count = headData.length;
    
            return (
                <View style={style.flex}>
                    {
                        headData.map( function(item,i){
                            return (
                                <View style={[style.center,{flex:1/count}]} key={i}>
                                    <TouchableOpacity onPress={ () => {update(headData[i])}}>
                                        <Text style={style.head_text}>
                                            {item}
                                        </Text>
                                    </TouchableOpacity>
                                </View>
                            )
                        })
                    }
                </View>
            )
        }
    }
    
    const style = StyleSheet.create({
        flex: {
            flex: 1,
            flexDirection: 'row'
        },
        head_text: {
            color: '#7B7B7B',
            fontSize: 20
        },
        center: {
            justifyContent: "center",
            alignItems: "center"
        }
    });

    LeftList.js【粒度组件:一级目录】

    import React, { Component } from 'react';
    import {
        StyleSheet,
        View,
        ScrollView,
        TouchableOpacity,
        Text,
        Dimensions
    } from 'react-native';
    
    const {width} = Dimensions.get('window');
    
    export default class LeftList extends Component{
    
        constructor(props){
            super(props);
            this.state = {
                selectIndex:0
            };
        }
    
        updateState(index,update,leftData){
    
            //触发回调函数
            update(leftData[index]);
    
            //重新渲染cell颜色
            this.setState({
                selectIndex:index
            })
        };
    
        componentWillReceiveProps(nextProps): void {
            if (nextProps.shouldChangeTab) {
                //重新渲染cell颜色
                this.setState({
                    selectIndex:0
                })
            }
        }
    
        render(){
    
            let leftData = this.props.data;
            let update = this.props.update;
            let {selectIndex} = this.state;
    
            return (
                <ScrollView style={style.container}>
                    {
                        leftData.map( (item,i) => {
                            return (
                                <View key={i} style={[style.list_cell,style.center, selectIndex === i ?
                                    style.selectBgColor : style.normalBgColor]}>
    
                                    <TouchableOpacity onPress = { this.updateState.bind(this,i,update,leftData) } >
    
                                        <Text style={[style.list_text,style.list_margin]}>
                                            {item}
                                        </Text>
    
                                    </TouchableOpacity>
    
                                </View>
                            )
                        })
                    }
                </ScrollView>
            )
        }
    }
    
    const style = StyleSheet.create({
        container: {
            flex:1,
             width/2,
            backgroundColor:'#F2F2F2'
        },
        list_text: {
            color: '#7B7B7B',
            fontSize: 18
        },
        list_margin: {
            marginLeft: 20
        },
        list_cell: {
            height: 60
        },
        center: {
            justifyContent: "center"
        },
        selectBgColor: {
            backgroundColor:'#FFFFFF'
        },
        normalBgColor: {
            backgroundColor:'#F2F2F2'
        }
    });

    RightList.js【粒度组件:二级目录】

    import React, { Component } from 'react';
    import {
        ScrollView,
        StyleSheet,
        Text,
        TouchableOpacity,
        View,
        Dimensions
    } from 'react-native';
    
    const {width} = Dimensions.get('window');
    
    export default class RightList extends Component{
    
        render(){
    
            let rightData = this.props.data;
    
            return (
                <ScrollView style={style.container}>
                    {
                        rightData.map( function(item,i){
                            return (
                                <View key={i} style={[style.list_cell,style.center]}>
                                    <TouchableOpacity>
                                        <Text style={[style.list_text,style.list_margin]}>
                                            {item}
                                        </Text>
                                    </TouchableOpacity>
                                </View>
                            )
                        })
                    }
                </ScrollView>
            )
        }
    }
    
    const style = StyleSheet.create({
        container: {
            flex:1,
             width/2,
            backgroundColor:'#FFFFFF'
        },
        list_text: {
            color: '#7B7B7B',
            fontSize: 18
        },
        list_margin: {
            marginLeft: 20
        },
        list_cell: {
            height: 60
        },
        center: {
            justifyContent: "center"
        }
    });

    MenuList.js【封装的复合组件】

    import React, { Component } from 'react';
    import {
        StyleSheet,
        View,
        Dimensions
    } from 'react-native';
    
    import HeadList from './HeadList'
    import LeftList from "./LeftList";
    import RightList from "./RightList";
    
    const {height} = Dimensions.get('window');
    
    let data = {};
    let headData = [];
    let leftData = [];
    let rightData = [];
    
    export default class MenuList extends Component{
    
        constructor(props){
            super(props);
            data = props.data;
    
            //初始化头部数据
            for (let item in data){
                headData.push(item);
            }
    
            //初始化左侧数据
            let defaultLValue = headData[0];
            for (let item in data[defaultLValue]){
                leftData.push(item);
            }
    
            //初始化右侧数据
            let defaultRValue = leftData[0];
            rightData = data[defaultLValue][defaultRValue];
    
            //初始化state
            this.state = {
                shouldChangeTab: false,
                currentTab: defaultLValue,
                leftData : leftData,
                rightData : rightData
            };
        }
    
        //函数回调,每次选择头部tab后,重新render
        forceUpdateAllUI = (ele) => {
            leftData = [];
            for (let item in data[ele]){
                leftData.push(item);
            }
            let defaultRValue = leftData[0];
            rightData = data[ele][defaultRValue];
    
            this.setState({
                shouldChangeTab:true,
                currentTab: ele,
                leftData: leftData,
                rightData: rightData
            })
        };
    
        //函数回调,每次选择左侧列表后,重新render
        forceUpdateRightListUI = (ele) => {
            rightData = data[this.state.currentTab][ele];
            this.setState({
                shouldChangeTab:false,
                rightData: rightData
            })
        };
    
        render(){
            return (
                <View style={style.container}>
                    <View style={style.top}>
                        <HeadList data={headData} update={this.forceUpdateAllUI}/>
                    </View>
                    <View style={style.bottom}>
                        <LeftList data={this.state.leftData}
                                  shouldChangeTab={this.state.shouldChangeTab}
                                  update={this.forceUpdateRightListUI}
                        />
                        <RightList data={this.state.rightData}/>
                    </View>
                </View>
            )
        }
    }
    
    const style = StyleSheet.create({
        container: {
            flex: 1,
            height: height,
            borderTopWidth: 1,
            borderBottomWidth: 1,
            borderColor: '#ddd'
        },
        top: {
            height: 60,
            borderBottomWidth: 1,
            borderColor:'#DFDFDF',
            backgroundColor:'#F5F5F5'
        },
        bottom: {
            height: height-60,
            flexDirection:'row',
            backgroundColor: '#F5FCFF'
        }
    });

    Index.ios.js【引用复合组件】

    /**
     * Sample React Native App
     * https://github.com/facebook/react-native
     * @flow
     */
    
    import React, { Component } from 'react';
    import {
        AppRegistry,
        StyleSheet,
        View,
        StatusBar
    } from 'react-native';
    import MenuList from "./src/MenuList";
    
    const data1 = {
        "全部区域": {
            "全部区域": ["全部区域"],
            "热门商圈": [
                "虹桥地区",
                "徐家汇地区",
                "淮海路商业区",
                "静安寺地区",
                "上海火车站地区",
                "浦东陆家嘴金融贸易区",
                "四川北路商业区",
                "人民广场地区",
                "南翔,安亭汽车城"
            ],
            "热门行政区": [
                "静安区",
                "徐汇区",
                "长宁区",
                "黄浦区",
                "虹口区",
                "宝山区",
                "闸北区"
            ]
        },
        "地铁沿线":{
            "地铁全线":["地铁全线"],
            "一号线":["莘庒站","外环路站","莲花路站","锦江乐园站","上海南站","漕宝路站"],
            "二号线":["浦东国际机场站","海天三路站","远东大道站","凌空路站"]
        }
    };
    
    const data2 = {
        "Language":{
            "All":["All"],
            "Web Front End":["HTML","CSS","JavaScript"],
            "Server":["Node.js","Java","Python","Ruby","Php"]
        },
        "Tool":{
            "All":["All"],
            "Apple":["Xcode"],
            "Other":["Sublime Text","WebStorm","Visual Studio Code"]
        }
    };
    
    StatusBar.setHidden(true);
    
    export default class RNComponentPackage extends Component {
    
        render() {
            return (
                <View style={styles.container}>
                    <MenuList data={data1}/>
                </View>
            );
        }
    }
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            backgroundColor: '#FFFFFF',
        }
    });
    
    AppRegistry.registerComponent('RNComponentPackage', () => RNComponentPackage);

      

    三、演示

     

  • 相关阅读:
    Ibatis 使用心得
    java.net.ConnectException: Connection timed out
    ZK 最少限度加载页面js文件
    JAVA 获取网页流
    ZK 页面间参数传递
    删除 TOMCAT 上次关闭遗留下来的 SESSION 缓存
    Java 异常java.lang.IllegalArgumentException: Illegal group reference
    ZK textbox Constraint验证
    zk textbox 更改字体大小及高度
    通过http管理solrcore
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/12606114.html
Copyright © 2011-2022 走看看