react(二):组件的通信

对于组件来说,通信无非两种,父子组件通信,和非父子组件通信

 

一、父子父子组件通信

  1、父组件给子组件传值

  对于父组件来说,props是他们之间的媒介

 

class Parent extends Component{
  state = {
    msg: 'start'
  };

  componentDidMount() {
    setTimeout(() => {
      this.setState({
        msg: 'end'
      });
    }, 1000);
  }

  render() {
    return <Child_1 msg={this.state.msg} />;
  }
}

class Child_1 extends Component{
  render() {
    return <p>{this.props.msg}</p>
  }
}

子组件通过接受父组件的props来获取父组件中的数据

  2、子组件给父组件传值

  途径是先在父组件中注册一个回调函数,子组件通过props获取到这一回调函数并执行

  

class Parent extends Component{
  state = {
    msg: 'start'
  };
  
  transferMsg(msg) {
    this.setState({
      msg
    });
  }

  render() {
    return <div>
        <p>child msg: {this.state.msg}</p>
        <Child_1 transferMsg = {msg => this.transferMsg(msg)} />
      </div>;
  }
}

class Child_1 extends Component{
  componentDidMount() {
    setTimeout(() => {
      this.props.transferMsg('end')
    }, 1000);
  }

  render() {
    return <div>
      <p>child_1 component</p>
    </div>
  }
}

  这样在子组件中用传参的方式,获取到子组件中的数据,进而改变了父组件的状态

  3、祖先组件给后代组件(就是组件之间的嵌套已经超过一层)

  这样的话也还可以通过props来传值,但是一层一层的传有点麻烦,我们可以使用... 运算符(三个点是es6里面的剩余展开属性),以更简洁的方式传递给更深层级的子组件。通过这种方式,不用考虑性能的问题,通过 babel 转义后的 ... 运算符 性能和原生的一致

class Child_1 extends Component{
render() {
return <div>
<p>{this.props.msg}</p>
<Child_1_1 {...this.props}/>
</div>
}
}

class Child_1_1 extends Component{
render() {
return <p>{this.props.msg}</p>
}
}

二、非父子组件之间的传值

   对于非父子组件来说缺少连接的纽带,很难通过props联系到一起(要是不是很远的话也能用,但是要是过深就特别麻烦),但是我们可以使用全局的一些机制来实现,比如react提供了一种上下文机制

class Brother1 extends React.Component{
  constructor(props){
    super(props);
    this.state = {}
  }
  
  render(){
    
    return (
      <div>
        <button onClick={this.context.refresh}>
            更新兄弟组件
        </button>
      </div>
    )
  }
}
Brother1.contextTypes = {
  refresh: React.PropTypes.any
}
class Brother2 extends React.Component{
  constructor(props){
    super(props);
    this.state = {}
  }
  
  render(){
    return (
      <div>
         {this.context.text || "兄弟组件未更新"}
      </div>
    )
  }
}
Brother2.contextTypes = {
  text: React.PropTypes.any
}
class Parent extends React.Component{
  constructor(props){
    super(props);
    this.state = {}
  }
  
  getChildContext(){
    return {
      refresh: this.refresh(),
      text: this.state.text,
      }
    }
  
  refresh(){
    return (e)=>{
      this.setState({
        text: "兄弟组件沟通成功",
      })
    }
  }
  render(){
    return (
      <div>
        <h2>兄弟组件沟通</h2>
        <Brother1 />
        <Brother2 text={this.state.text}/>
      </div>
    )
  }
}
Parent.childContextTypes = {
  refresh: React.PropTypes.any,
  text: React.PropTypes.any,
}

使用方法

使用getChildContext方法将属性传递给子组件,并使用childContextTypes声明传递数据类型,子组件中需要显式地使用contextTypes声明需要用到的属性的数据类型。

需要传递进context参数才可以在constructor方法中使用context,要不然React将会报错。

在组件中,通过this.context访问context中的属性或方法。

 

未完待续。。。

关于组件之间的通信还有更好的方式,比如说用redux来管理数据流,之后单独整理关于redux的部分。

posted @ 2018-05-29 19:52  Rachid  阅读(321)  评论(1编辑  收藏  举报