React之间的组件通信的关系分为以下三种:
- 父子组件
- 兄弟组件(相互无关联关系)
- 祖孙组件(多层嵌套)
介绍一下常用的组件间通信的方式:
- props传值:
(1)基本 props
(2)render props- 基于消息订阅-发布者模式的组件传值:
常用的有pubs-sub- 集中式管理:
通常使用redux、dva等中间件- 基于生产者消费者模式的组件传值:
常用的有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>
);
}