React-Native开发八 react-navigation之自定义组件Counter

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiyei2009/article/details/81589878

1 前言

我们知道RN中任何界面元素都可以看成组件,小到一个按钮,大到一个页面。RN开发就是不停的开发组件和使用组件,并让他们协同工作,这样高效率协同的运行起来,这样就能完成一个APP的功能了
在实际的开发中,我们经常需要自定义一些满足我们项目开发的自定义组件,类似于Android开发中的自定义View。不过RN中自定义组件比Android中自定义View稍微简单一些。下面以一个计数器Counter的例子来记录一下RN中自定义的组件的开发流程。

这里写图片描述

2 RN中自定义组件步骤

一般来说RN中自定义组件有以下几步
1 继承RN的Component
这个不必说,只有是它的子类我们才能被RN渲染出对应的View视图

2 复写render()方法返回组件的视图呈现
这个方法主要是返回一个我们组件想呈现出的界面,例如时一个圆,长方形,还是不规则图形,或者说一些View的组合等。

3 定义组件属性以便于组件与父组件或子组件的交互接口
因为一般来说,我们的组件都是需要来使用的,有可能被当做子组件使用,这个时候需要父组件给它传递一些属性,或者它作为某些组件的父组件来使用。因此我们需要定义好一些属性作为组件对外交互的接口

4 处理组件的内部逻辑
这里主要涉及到组件的内部逻辑,比如点击事件,触摸事件,以及相应内部state状态的维护等

5 使用组件
主要需要注意的是,是否需要传递给组件的属性,以及使用组件的功能等。

3 自定义Counter组件

我们以最开头的一个计数器为例,它主要有以下功能
1 点击+,可以使计数器+1
2 点击-,可以让计数器-1
3 可以具体输入具体值
4 外部组件可以调用组件的getCount()获取最终的值
5 当计数器的值发生改变时可以回调给使用它的父组件
基于以上需求,我们可以定义如下的一个Counter组件

import React,{ Component } from 'react';
import {StyleSheet, Text, TextInput, TouchableOpacity, View} from "react-native";
import {PropTypes} from "prop-types";

/**
 * 计数器
 */
export default class Counter extends Component{

    /**
     * 定义默认属性
     * @type {{}}
     */
    static defaultProps = {
        initValue:0,
    };

    /**
     * 属性类型
     * @type {{}}
     */
    static propTypes = {
        initValue:PropTypes.number,
        onValueChange:PropTypes.func,
    };

    /**
     * 构造方法
     * @param props
     */
    constructor(props){
        super(props);

        //初始状态
        this.state = {
            value : this.props.initValue,
        };
    }

    //组件渲染布局
    render(){
        return (
            <View style={[styles.operatingBox,this.props.styles]}>
                <TouchableOpacity activeOpacity={0.2}
                                  style={styles.reduce}
                                  onPress={this.reduce.bind(this)}>
                    <Text allowFontScaling={false} style={styles.btn1}>-</Text>
                </TouchableOpacity>

                <View style={styles.inputBox}>
                    <TextInput style={styles.input1}
                               value={this.state.value.toString()}
                               maxLength={9}
                               keyboardType='numeric'
                               autoFocus={false}
                               underlineColorAndroid='transparent'
                               onEndEditing={this.checkInput.bind(this)}
                               onChangeText={this.onChangeText.bind(this)}>
                    </TextInput>
                </View>

                <TouchableOpacity activeOpacity={0.2}
                                  style={styles.plus}
                                  onPress={this.plus.bind(this)}>
                    <Text allowFontScaling={false} style={styles.btn1}>+</Text>
                </TouchableOpacity>
            </View>
        );
    }

    //减少计数
    reduce(){
        this.updateValue(this.state.value-1);
    }

    //增加计数
    plus(){
        this.updateValue(this.state.value+1);
    }

    updateValue(newValue){
        this.setState({
            value: newValue,
        });
        this.props.onValueChange(newValue);
    }

    //检查输入的内容
    checkInput(){
        let res = this.state.value;
        if (res === '' || res < 0) {
            res = 0;
        } else {
            res = Math.floor(res); //舍去小数
        }
        this.updateValue(res);
    }

    //内容改变函数
    onChangeText(txt){
        this.setState({
            value:Number(txt)
        });
        this.props.onValueChange(Number(txt));
    }

    //返回数值
    getCount(){
        return this.state.value;
    }

}

//样式
const styles = StyleSheet.create({
    operatingBox: {
        margin:5,
        width: 120,
        height:35,
        borderColor:'gray', //边框颜色
        borderWidth:1,
        borderRadius: 5, //圆角半径

        flexDirection:'row', //主轴布局
        alignItems: 'center', //侧轴对齐方式
        overflow: 'hidden', //超过控件范围的隐藏
    },
    btn1:{
        fontSize:18,
        textAlign:'center',
        backgroundColor:'transparent', //透明颜色
    },
    inputBox:{
        flex:1, //
        borderRightWidth:1, //右边距
        borderRightColor:'gray', //颜色
    },
    reduce:{
        width:34,
        height:34,
        justifyContent:'center',
        borderRightWidth:1, //右边距
        borderRightColor:'gray', //颜色
    },
    plus:{
        width:34,
        height:34,
        justifyContent:'center',
    },
    input1:{
        flex:1,
        backgroundColor:'transparent', //透明
        textAlign:'center',
        padding:0,
        fontSize:14,
    },
});

可以看到,我们最外层View定义了一个圆角矩形框,然后分别使用了两个按钮,一个输入框来完成我们的功能。

并且定义了如下属性
initValue:PropTypes.number, //初始值
onValueChange:PropTypes.func, //回调函数

在内部定义了状态value,用于显示具体的值

并且定义了一个方法用于获取value

    //返回数值
    getCount(){
        return this.state.value;
    }

4 使用Counter组件

使用该组件很简单,我们直接在父组件中引用它即可,如下:

import React,{Component} from "react";
import {View, StyleSheet, Text, TouchableOpacity} from "react-native";
import Counter from "../component/Counter";


export default class CountDemo extends Component{

    constructor(props) {
        super(props);
        this.state = {
            value: 0,

        };
    }

    render() {
        return (
            <View style={styles.container}>
                <Counter
                    ref={(count) => this.count = count}
                    initValue={10}
                    onValueChange={(value) => this._onValueChange(value)}
                />
                <View>
                    <Text>{this.state.value}</Text>
                </View>
                <TouchableOpacity onPress={() => this.getValue()}>
                    <Text>点击获取值</Text>
                </TouchableOpacity>
                <TouchableOpacity onPress={() => this.clearValue()}>
                    <Text>清理</Text>
                </TouchableOpacity>
            </View>
        );
    }

    _onValueChange(value) {
        this.setState({
            value:value,
        });
    }

    getValue(){
        this.setState({
            value:this.count.getCount(),
        });
    }

    clearValue(){
        this.setState({
            value:0,
        });
    }
}

//样式
const styles = StyleSheet.create({
    container: {
        flex:1,
        borderColor:'#DDD', //边框颜色
        alignItems: "center"
    },
    count:{
        backgroundColor:"#FF22FF",//
        width:50,
        height: 30,
    }
});

运行效果如下:
这里写图片描述

参考:
另外源码请参考如下:
https://github.com/qiyei2015/ReactNative/tree/master/project/GitHub

猜你喜欢

转载自blog.csdn.net/qiyei2009/article/details/81589878
今日推荐