react没有嵌套关系的组件之间通信方法详解
一、在react中,没有嵌套关系的组件之间的通信方式主要有2种:
a、拥有共同父组件的兄弟组件之间可以使用context。
具体使用方法可以参考:https://www.jianshu.com/p/a8717edadb18
b、非兄弟组件之间利用事件的发布订阅模式。
1)事件的发布订阅模式是什么?首先需要一个发布者,和一个或多个订阅者。假如我家有一个水果店,张三来我家买苹果,正好我家苹果卖完了,我就告诉他一个电话号码,让他回去等电话,苹果一到货,我就通知他(但是他可以选择再去买或者不去买,只是我一定会通知他),同样李四也是同样的需求,我给出了同样的解决方案,以此类推。。。等苹果到货了,我会按照先后顺序挨个给所有的预订者打电话通知。在这个事件当中,张三和李四就是订阅者,而我就是发布者,我打电话通知他们的动作就是发布者对订阅事件的处理函数。所以在react组件之间的通信场景里,只要组件1负责订阅(监听事件),组件2负责发布(触发事件)就可以进行数据交流。
2)如何实现?核心代码如下:
//组件1(负责订阅事件和取消订阅事件)
import emitter from './events';
componentDidMount () { //在组件挂载完成后声明一个自定义事件
emitter.addListener('callMe', (msg) => {
this.setState({
msg: msg
})
})
}}
componentWillUnmount () { //组件销毁前移除事件监听
emitter.removeListener('callMe', (msg) => {
this.setState({
msg: msg
})
)
//组件2(负责发布事件)
import emitter from './events';
render () {
function publ(){
return function () {
emitter.emit('callMe', '我是发布者');
}
}
return (
<div>
我是负责发布事件的组件2 <button onClick = {publ()}>点击我</button>
</div>
)
}
可以看的出来,我们在组件内分别引入一个events包,它提供了监听、发布、删除等事件处理方法,是一个在浏览器端实现了node事件机制的包。源码解析可以参考:http://blog.csdn.net/leoleocs/article/details/50162065
这里我们主要用到3个核心方法:事件监听(订阅)、事件触发(发布)和事件删除(取消订阅)。现在来理解一下这3个方法的底层实现原理(需要自行参照源码来理解):
事件监听:addListener方法,首先需要传入2个参数(type, lintener),事件名称和对应的处理函数。然后定义一个_events空对象,用来存储订阅事件列表,当组件挂载完成以后,程序会自动触发这个方法进行遍历所有监听事件,并以数组的形式存储起来。
事件触发:emit方法,它只需要传入type参数,即要发布的事件名称。当用户触发此方法的时候,首先需要通过事件名称找对应的事件处理函数handler,调用isFunction方法检测它是否为一个函数,如果是,通过call和apply方法将函数执行者指向当前调用的对象,并将事件处理函数作为参数传入。
事件删除:removeListener方法,它也需要传入2个参数(type, lintener),事件名称和对应的处理函数。当组件即将销毁之前自动触发此方法,先得到当前事件的处理函数,然后与传入的处理函数lintener对比,如果二者一样,则直接删除,如果lintener还处于等待触发的队列中,则直接退出队列。