react(二)父子组件间的数据传递---prop

react组件的数据分为两种,prop(代表property)和state。

1、父子组件间的数据传递主要使用prop。
2、子组件接收的prop的数据格式是由prop-types进行检测的,当不符合时,会在console控制台提出警告(可用于开发环境)。

prop的类型:不同的类型实现了父子组件间不同方向的数据传递

一、普通数据类型:可用于外部世界向子组件内部传递数据。

注意:这里是使用了create-react-app快速搭建了react结构。

(1)入口js文件:

其中ControlPanel是自定义组件。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import ControlPanel from './ControlPanel';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(<ControlPanel />, document.getElementById('root'));
registerServiceWorker();

(2)ControlPanel自定义父组件的定义,其中Counter是子组件。

import React ,{Component} from 'react';
import Counter from './Counter';

export default class ControlPanel extends Component{
    render(){
        return (
            <div>
                {/*使用多个子组件,并且通过两个prop向子组件Counter进行数据传递:caption和initValue。*/}
                <Counter caption="First" initValue={0}></Counter>
                <Counter caption="Second" initValue={10}></Counter>
                <Counter caption="Third" initValue={20}></Counter>
            </div>
        )
    }
}

(3)Counter子组件内容:

注意:
当当前组件需要使用父组件通过prop传递过来的数据时,必须在构造函数的第一行调用父类(React.Component)构造函数,即super(props)。即this.props的赋值是React.Compnent构造函数的工作之一。


import React,{Component} from 'react';
// 注意:react最新版本已经将proptypes独立出来,需要自行安装prop-types才可以使用。
import PropTypes from 'prop-types';

//直接在定义组件的时候,将组件导出。
export default class Counter extends Component{
    constructor(props){
        super(props);
        this.onJia=this.onJia.bind(this);
        this.onJian=this.onJian.bind(this);
        this.state={
            // 使用父组件传递过来的初始值,这里可以用短路操作,也可以使用下面提到的defaultProps来进行设置
            counter:props.initValue||0
        }
    }
    onJia(){
        this.setState({
            counter:this.state.counter+1
        })
    }
    onJian(){
        this.setState({
            counter:this.state.counter-1
        })
    }
    render(){
        const btnStyle={
            margin:"0 20px"
        };
        return (
            <div>
                {/*获取到父组件传递的文字内容*/}
                {this.props.caption}:
                <button onClick={this.onJia} style={btnStyle}>+</button>
                <span>{this.state.counter}</span>
                <button onClick={this.onJian} style={btnStyle}>-</button>
            </div>
        )
    }
}
// 这个propTypes只能在开发阶段辅助检测父向子传递数据的类型及是否必备。
// 在生产环境中,无意义,可使用 babel-react-optimize 去掉propTypes验证。
Counter.propTypes={
    caption:PropTypes.string.isRequired,
    initValue:PropTypes.number
}

// defaultProps 用于设置默认值,当父向子组件未传递时的默认值。
Counter.defaultProps={
    initValue:0
}

二、函数数据类型:相当于父组件向子组件传递了一个函数,在子组件内部某一个时刻执行这个函数,就会将子组件的数据传递给父组件中。

(1)步骤一:在父组件中定义函数,约定参数。

(2)步骤二:给指定的子组件设置传递的属性

(3)步骤三:在子组件中,确定父组件传递过来的函数 *执行 *的位置,及传入的参数。

  • 应用实例:子组件做任意修改,父组件均正常显示总和。
    在父组件中实时显示多个子组件的总和。

修改ControlPanel文件内容如下:



import React ,{Component} from 'react';
import Counter from './Counter';

export default class ControlPanel extends Component{
    constructor(props){
        super(props);
        this.onCounterUpdate=this.onCounterUpdate.bind(this);
        // 每一个ContrlPanel组件类的私有属性
        this.initValues=[0,10,20];
        // 获得初始加和的值,reduce函数获取到加和结果,如果没有默认为0。
        const initSum=this.initValues.reduce((a,b)=>a+b,0);
        this.state={
            sum:initSum
        }
    }
    // 步骤一:在父组件中定义函数,约定参数。

    // 在父组件中定义函数,约定参数一是更新后的值,参数二是原值。
    onCounterUpdate(newValue,previousValue){
        const valueChange=newValue-previousValue;
        // 触发state值的改变,引发重新渲染。
        this.setState({
            sum:this.state.sum+valueChange
        })
    }
    render(){
        return (
            <div>
                {/*步骤二:给指定的子组件设置传递的属性*/}
                {/*通过给子组件设置属性的方式传递定义的函数onCounterUpdate*/}
                <Counter caption="First" initValue={this.initValues[0]} onUpdate={this.onCounterUpdate}></Counter>
                <Counter caption="Second" initValue={this.initValues[1]} onUpdate={this.onCounterUpdate}></Counter>
                <Counter caption="Third" initValue={this.initValues[2]} onUpdate={this.onCounterUpdate}></Counter>
                <hr/>
                {/*展示总和*/}
                <div>Total Count:{this.state.sum}</div>
            </div>
        )
    }
}

修改Counter文件内容如下:


import React,{Component} from 'react';
// 注意:react最新版本已经将proptypes独立出来,需要自行安装prop-types才可以使用。
import PropTypes from 'prop-types';

export default class Counter extends Component{
    constructor(props){
        super(props);
        this.onJia=this.onJia.bind(this);
        this.onJian=this.onJian.bind(this);
        this.state={
            // 使用父组件传递过来的初始值
            counter:props.initValue||0
        }
    }
    onJia(){
        this.updateCount(true);
    }
    onJian(){
        this.updateCount(false);
    }
    // 增加、减少共用此函数
    updateCount(isIncrement){
        const previousValue=this.state.counter;
        const newValue=isIncrement?previousValue+1:previousValue-1;
        this.setState({counter:newValue});
        // 步骤三:在子组件中,确定父组件传递过来的函数执行的位置,及传入的参数。(此案例中,需要在每一次加减按钮操作时,均实时显示出总和,所以写在了公共函数的内部)

        // 在子组件中调用传递过来的函数,实参一是新值,实参二是老值。
        // 一旦调用,就会触发state的更新,从而引发重新渲染。
        this.props.onUpdate(newValue,previousValue);
    }
    render(){
        const btnStyle={
            margin:"0 20px"
        };
        return (
            <div>
                {this.props.caption}:
                <button onClick={this.onJia} style={btnStyle}>+</button>
                <span>{this.state.counter}</span>
                <button onClick={this.onJian} style={btnStyle}>-</button>
            </div>
        )
    }
}

Counter.propTypes={
    caption:PropTypes.string.isRequired,
    initValue:PropTypes.number,
    onUpdate:PropTypes.func
};
Counter.defaultProps={
    initValue:0,
    onUpdate:f=>f
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值