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

来源:互联网 发布:effective java 第3版 编辑:程序博客网 时间:2024/05/28 19:25

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};