父子组件通信

数据流

  • react是单向数据流,即从组件树的顶部传往底部
  • 子组件通过prop的形式从父组件接收数据,props无法直接修改

(一)数据传递

父组件向子组件传递数据

父组件在子组件上声明一个属性,并将数据放在对应属性值上,在子组件中,使用this.props.属性名访问。

class Parent extends Component {
  render() {
    return (
     <Child myData={'123'}/>
    );
  }
}
​
class Child extends Component {
  render() {
    return (
      <div>
        子组件
      </div>
    );
  }
  componentDidMount(){
    console.log(this.props.myData)
  }
}

子组件向父组件传递数据

子组件向父组件传递数据需要通过回调函数。

首先,我们在子组件上声明一个属性,属性对应的值是方法。该方法用于接收子组件传入的数据。

在子组件中,我们在传递数据标志触发之后,通过this.props.属性名的方式触发父组件中获取子组件传入数据的方法,并且将数据传入。

//    父组件
class Parent extends Component {
  constructor(){
    super()
  }
  getChildData(val){
    console.log(val)
  }
  render() {
    return (
     <Child ChildData={this.getChildData} />
    );
  }
}

//    子组件
class Child extends Component {
  constructor(){
    super();
    this.transferData = this.transferData.bind(this);
  }
  transferData(){
    this.props.ChildData({
      name:"传递子组件数据",
      content:"子数据数据"
    })
  }
  render() {
    return (
      <div>
        <button onClick={this.transferData}>点击传递数据给父组件</button>
      </div>
    );
  }
}

(二)方法调用

父组件调用子组件的方法

通过refs:在子组件上声明一个ref值,那么在需要调用时,使用this.refs的方式即可调用子组件的方法。

//    父组件
class Parent extends Component {
  constructor(){
    super()
    this.doChildMethod = this.doChildMethod.bind(this);
  }
  doChildMethod(){
    this.myChild.showMe();
  }
  render() {
    return (
    <React.Fragment>
      <Child ChildData={this.getChildData} ref="myChild" />
      <button onClick={this.doChildMethod}>点击执行子组件的方法</button>
    </React.Fragment>
    );
  }
}

//    子组件
class Child extends Component {
  constructor(){
    super();
    this.showMe = this.showMe.bind(this);
  }
  showMe(){
    console.log('我是子组件,你调用我啦!');
  }
  render() {
    return (
      <div>
        <div>子组件</div>
      </div>
    );
  }
}

子组件调用父组件的方法

与子组件传值给父组件

// Parent Component
<ChildComponent beforeClick={this.beforeClick} />
beforeClick: function(name) {
    if (name === 'vine') {
      alert('这是vine写的');
      return false;
    }
    return true;
}

//    Children Component
render: function() {
    return <button onClick={this.alertMe}>click me </button>;
  },
alertMe: function() {
    if (!this.props.beforeClick('vine')) {
      return false;
    }
    alert('我被点击了!');
}

(三)特殊情况

因为state异步而得不到props的值

如果有以下情况我们会得不到props的值:

  1. 我们在父组件中将state当做初始值传给了子组件。

  2. 在传之前,我们在父组件中做了setState的操作,该操作为异步操作。

  3. 在子组件的componentDidMount访问传过来的state值,结果为空。

那么,以下方案可以解决这个问题,比如我们要传的数据为myData,那么以下方式可以得到myData。这里要注意对myData长度的判断。

componentWillReceiveProps(nextProps){
    if(nextProps.myData!==this.props.myData){
        this.setData({
            myData:nextProps.myDatas;
        })
    }
}