美文网首页React JSWeb前端之路WEB前端程序开发
React学习教程(6)state高级应用

React学习教程(6)state高级应用

作者: 四冶读史 | 来源:发表于2017-10-30 08:54 被阅读27次

概述

React规则规定,state只能被拥有它的组件修改。
如果有几个组件需要同步state该如何处理?
即,其中一个组件更改state,其它组件state保持同步,反之亦然。
要保持state同步,各组件必须拥有共同的“数据源”,当一个组件的state发生变化,将其state的值提高到各组件最近共同的父组件中,然后由父组件统一传递给各组件,其它组件亦然。
state只能由拥有它的组件改变,那么子组件又是如何使父组件的state改变呢?
==父组件创建一个改变state函数;
==将该函数作为props的属性传递到子组件;
==子组件调用该函数使父组件的state改变;
完美!
记住,数据自定往下流。
我现在要做个小程序,两个输入框,一个输入人民币,一个输入美元,当输入人民币时,美元输入框显示人民币转换后的美元,当输入美元时,人民币输入框显示美元转换后的人民币。
且看如何实现。
创建Money类组件

/**
 * Money组件
 */
class Money extends Component{
    constructor(props){
        super(props);
        //
   }
​
    render(){
        return(
            <div>
                <input type="text" />
            </div>
       );
   }
}

用来渲染输入框的。

创建汇率类组件

ExchangeRate组件2次渲染Money组件,一次表示人民币,一次表示美元

/**
 * 汇率组件
 */
class ExchangeRate extends Component{
    constructor(props){
        super(props);
        //
   }
​
    render(){
        return(
            <div>
                <Money />
                <Money />
            </div>
       );
   }
}

创建Money标志

const MoneyTag = {
    Y: 'CNY',
    D: 'Dollar'
}

Y表示人民币
D表示美元
并在ExchageRate组件中初始化state

this.state = {
            tag: 'Y',
            num: ''
       }

tag:类型,默认人民币
num:输入的金额,默认为空

创建汇率转换函数

    /**
     * 美元转换成人民币
     * @param {*} num 
     */
    to_cny(num){
        return num * 6.6392;
   }
​
    /**
     * 人民币转换成美元
     * @param {*} num 
     */
    to_dollar(num){
        return num * 0.1506;
   }
​
    /**
     * 汇率转换
     * @param {*} tag 
     * @param {*} num 
     */
    exchange_rate_change(tag,num){
        const input = parseFloat(num);
        if(Number.isNaN(input)){
            return '';
       }
        // 转换成美元
        if(tag === 'Y'){
            return Math.round(this.to_dollar(input) * 1000000) / 1000000;
       }
        // 转换成人民币
        return Math.round(this.to_cny(input) * 1000000) / 1000000;;
   }

输入的是人民币,则需要转换成美元;
输入的是美元,则需要转换成人民币;

将参数专递给子组件

    render(){
        const tag = this.state.tag;
        const num = this.state.num;
        const cny = tag === 'Y' ? num : this.exchange_rate_change(tag,num);
        const dollar = tag === 'D' ? num : this.exchange_rate_change(tag,num);
        return(
            <div>
                <Money tag='Y' num={cny} />
                <Money tag='D' num={dollar} />
            </div>
       );
   }

子组件获取参数并展示

<input type="text" value={this.props.num} />

汇率(ExchangeRate)组件添加状态改变函数

     /**
     * 改变状态
     * @param {*} tag 
     * @param {*} num 
     */
    handle_change(tag,num){
        this.setState({
            tag: tag,
            num: num
       });
   }

如果要使用this.setState这个方法,就需要绑定this,因为如果不绑定,那么this.setState中的this指的是handle_change这个方法,显然该方法并没有setState这个方法,故而会报错。当然,也可以使用箭头函数(后面再讲)。
绑定this:

constructor(props){
        super(props);
        this.state = {
            tag: 'Y',
            num: ''
       }

        // 绑定this
        this.handle_change = this.handle_change.bind(this);
   }

此时handle_change中的this指的就是对象(ExchangeRate)本身了。
状态函数要像属性一样,通过props传递给子组件:

<div>
    <Money tag='Y' num={cny} handle_change={this.handle_change} />
    <Money tag='D' num={dollar} handle_change={this.handle_change} />
</div>

子组件(Moeny)添加onChange函数

监听输入框的变化,并调用父组件传递过来的handle_change函数,使父组件的state改变:

/**
 * Money组件
 */
class Money extends Component{
    constructor(props){
        super(props);
        //
   }
​
    /**
     * 输入金额切换状态
     * @param {*} e 
     */
    handle_change(e){
        this.props.handle_change(this.props.tag,e.target.value);
   }
​
    render(){
        return(
            <div>
                <input type="text" value={this.props.num} onChange={(e) => {
                    this.handle_change(e);
               }} />
            </div>
       );
   }
}

此时,
你在人民币输入框输入金额,美元输入框就会自动兑换;
你在美元输入框输入金额,人民币输入框就会自动兑换;

添加金额符号

为了便于区别,需在输入框后面添加金额符号

    render(){
        const symbol = this.props.tag === 'Y' ? "Y" : "$";
        return(
            <div>
                <input type="text" value={this.props.num} onChange={(e) => {
                    this.handle_change(e);
               }} />{symbol}
            </div>
       );
   }

为了简化,暂用“Y”替代人民币符号

效果展示

Paste_Image.png

完整代码

const MoneyTag = {
    Y: 'CNY',
    D: 'Dollar'
}
​
/**
 * Money组件
 */
class Money extends Component{
    constructor(props){
        super(props);
        //
   }
​
    /**
     * 输入金额切换状态
     * @param {*} e 
     */
    handle_change(e){
        this.props.handle_change(this.props.tag,e.target.value);
   }

    render(){
        const symbol = this.props.tag === 'Y' ? "Y" : "$";
        return(
            <div>
                <input type="text" value={this.props.num} onChange={(e) => {
                    this.handle_change(e);
               }} />{symbol}
            </div>
       );
   }
}

/**
 * 汇率组件
 */
class ExchangeRate extends Component{
    constructor(props){
        super(props);
        this.state = {
            tag: 'Y',
            num: ''
       }

        // 绑定this
        this.handle_change = this.handle_change.bind(this);
   }

    /**
     * 美元转换成人民币
     * @param {*} num 
     */
    to_cny(num){
        return num * 6.6392;
   }
​
    /**
     * 人民币转换成美元
     * @param {*} num 
     */
    to_dollar(num){
        return num * 0.1506;
   }
​
    /**
     * 汇率转换
     * @param {*} tag 
     * @param {*} num 
     */
    exchange_rate_change(tag,num){
        const input = parseFloat(num);
        if(Number.isNaN(input)){
            return '';
       }

        // 转换成美元
        if(tag === 'Y'){
            return Math.round(this.to_dollar(input) * 1000000) / 1000000;
       }
        // 转换成人民币
        return Math.round(this.to_cny(input) * 1000000) / 1000000;;
   }
​
    /**
     * 改变状态
     * @param {*} tag 
     * @param {*} num 
     */
    handle_change(tag,num){
        this.setState({
            tag: tag,
            num: num
       });
   }
​
    render(){
        const tag = this.state.tag;
        const num = this.state.num;
        const cny = tag === 'Y' ? num : this.exchange_rate_change(tag,num);
        const dollar = tag === 'D' ? num : this.exchange_rate_change(tag,num);
        return(
            <div>
                <Money tag='Y' num={cny} handle_change={this.handle_change} />
                <Money tag='D' num={dollar} handle_change={this.handle_change} />
            </div>
       );
   }
}

const element = (
    <div>
        <ExchangeRate />
    </div>
);

ReactDOM.render(
    element,
    document.getElementById('root')
);

注:
本教程相关的所以源码,可在https://github.com/areawen2GHub/reacttest.git下载

参考地址:
https://react.bootcss.com/react/docs/lifting-state-up.html

相关文章

网友评论

    本文标题:React学习教程(6)state高级应用

    本文链接:https://www.haomeiwen.com/subject/zntppxtx.html