React组件间通信方式总结

React之间的组件通信的关系分为以下三种

  1. 父子组件
  2. 兄弟组件(相互无关联关系)
  3. 祖孙组件(多层嵌套)

介绍一下常用的组件间通信的方式

  1. props传值:
    (1)基本 props
    (2)render props
  2. 基于消息订阅-发布者模式的组件传值:
    常用的有pubs-sub
  3. 集中式管理:
    通常使用redux、dva等中间件
  4. 基于生产者消费者模式的组件传值:
    常用的有context

下面来逐个介绍一下每个方式的使用场景:

一、props传值
现在有一个场景,App组件中包含有A和B两个组件,A是B父组件,A给B传值最简单的是通过props的方法:
(1)基本 props传值:

import React, { Component } from "react";

class A extends Component {
  
  state={
    car:'特斯拉'
  }

  render() {
    const {car} =this.state
    return <div>
      我是A组件,我的车是{car}
      <B car={car}/>
      </div>;
  }
}

class B extends Component {
  render() {
    return <div>我是B组件,我从A组件收到的车是{this.props.car}</div>;
  }
}


export default class App extends Component {
  render() {
    return <div><A/></div>;
  }
}

(2)render props传值:
这里利用了父组件A调用返回的render函数(这里的render和生命周期的render不同,完全可以自定义名称),实现给B组件传值并且渲染。

class A extends Component {
  state = {
    car: "特斯拉",
  };

  render() {
    const { car } = this.state;
    return (
      <div>
        我是A组件,我的车是{car}
        {this.props.render(car)}
      </div>
    );
  }
}

class B extends Component {
  render() {
    return <div>我是B组件,我从A组件收到的车是{this.props.car}</div>;
  }
}

export default class App extends Component {
  render() {
    return (
      <div>
        <A render={(data) => <B car={data} />}></A>
      </div>
    );
  }
}

二、基于消息订阅-发布者模式的组件传值

这种方式需要安装pubsub-js插件,实现消息的发布和订阅。执行以下命令安装插件:

npm install pubsub-js

这种模式的应用场景是兄弟组件之间传值,现在有A和B两个兄弟组件,如果A要给B传值,那么A的身份就是发布者,B的身份就是订阅者。实现代码很简单:

class A extends Component {
  state = {
    car: "特斯拉",
  };

  publishMessage = () => {
    //当点击按钮以后发布为car的消息,所有订阅此消息的组件都可以接收到并且处理回调
    PubSub.publish("car", this.state.car);
  };

  render() {
    return (
      <button onClick={this.publishMessage}>
        点击我给兄弟组件B传汽车的名字
      </button>
    );
  }
}

class B extends Component {
  state = {
    car: "",
  };

  componentDidMount() {
    //当组件初始化的时候就开始监听订阅,出现类型为car的消息,立马调用回调函数mySubscriber
    this.token = PubSub.subscribe("car", this.mySubscriber);
  }

  mySubscriber = (msg, data) => {
    this.setState({
      car: data,
    });
  };

  componentWillUnmount() {
    //当B组件销毁的时候,取消订阅
    PubSub.unsubscribe(this.token);
  }

  render() {
    return <div>我现在的车是{this.state.car}</div>;
  }
}
export default class App extends Component {
  render() {
    return (
      <div>
        <A />
        <B />
      </div>
    );
  }
}

三、集中式管理

集中式管理数据的模式较为复杂,可以参考我其他关于redux的学习总结:
iron-redux学习记录
redux使用记录

四、 基于生产者消费者模式的组件传值

context一般用于祖组件与孙组件之间也就是多层嵌套的组件进行传值。

const CarContext = React.createContext();
class A extends Component {
  state = {
    car: "特斯拉",
  };

  render() {
    const { car } = this.state;
    return (
      <div>
        我是第一层组件,我的车名字是:{car}
        <CarContext.Provider value={car}>
          <B />
        </CarContext.Provider>
      </div>
    );
  }
}

class B extends Component {
  render() {
    return (
      <div>
        我是第二层组件
        <C />
      </div>
    );
  }
}

class C extends Component {
  render() {
    return (
      <div>
        我是第三层组件
        <D />
      </div>
    );
  }
}

class D extends Component {
  static contextType = CarContext;

  render() {
    return <div>我是第四层组件,我接收到的车名字是:{this.context}</div>;
  }
}



export default class App extends Component {
  render() {
    return (
      <div>
        <A />
      </div>
    );
  }
}

这里的D组件如果是函数组件的话,还有另外一种写法:

function D() {
  return (
    <div>
      <CarContext.Consumer>
        {(value) => `我是第四层组件,我接收到的车名字是:${value}`}
      </CarContext.Consumer>
    </div>
  );
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值