在常用的MVVM框架比如vue,组件间通信可能会有以下三种情况:
1. 父子通信:通过props
2. 非父子组件组件用eventBus通信
3. 如果项目很大,数据需要共享到多个组件(跨组件通信,改同一个数据等),用vuex管理
那么文中的eventBus是怎么实现的呢,就是根据发布订阅模式。发布订阅模式应用广泛,js事件就是一个经典的发布订阅模式。看个例子addEventListener
EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行,事件目标可以是一个文档上的元素 Document 本身。
target.addEventListener(type, listener, options);
//type 表示事件类型(eg:click)
//listener 回调函数,当监听的事件类型触发时,执行listener函数
//options 冒泡还是捕获等参数
原生js中,我们通过addEventListener注册事件(订阅),比如鼠标点击,传入回调函数(在注册的事件触发时要执行的函数),那么鼠标点击时(发布),传入的回调函数就会执行。除了原生js事件。
那一个简单的发布订阅模式怎么实现呢?定义一个EventEmitter类,它有以下几个元素:
- 单例对象,维护订阅者:单例模式就是为保证不同的人实例化EventEmitter类之后,拿到的状态是同一个。
- 订阅方法:传入订阅的事件类型及回调函数,订阅事件
- 发布方法:传入发布的事件类型及参数(传给回调函数的),发布事件。发布时,会执行订阅时传入的回调函数
- 移除方法:移除订阅(监听)的回调函数
代码如下:
class EventEmitter {
constructor(){
//单例模式
this._events = this._events || new Map();
}
//发布(触发事件)
emit(type, ...args){
//拿到订阅者的回调函数
var handler = this._events.get(type);
if(!handler){
return;
}
//发布时,依次执行订阅者的回调
for(var i = 0; i< handler.length; i++){
handler[i].apply(this, args);
}
}
//订阅(监听事件)
addListener(type, func){
var handler = this._events.get(type);
//如果还没有同类型的订阅,新创建一个
if(!handler){
this._events.set(type, [func]);
return;
}
//把回调函数塞入数组
handler.push(func);
}
//移除
removeListener(type, func){
var handler = this._events.get(type);
if(!handler){
return;
}
for(var i = handler.length; i>0; i--){
//找到自己要移除的函数,匿名函数不能移除
if(handler[i] == func){
handler.splice(i, 1);
}
}
}
}
该实现只是探究原理,异常处理之类的都没做。想了解单例模式可以看:《javaScript设计模式与开发实践》(我还没看完emmm)
参考:
[eventBus实现][2]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。