给一个主题添加若干个观察者,若主题有变更,则通知所有的观察者,观察者收到通知后可以做一些处理,下面是一个简易版的实现
// 主题类
class Subject {
constructor () {
this.watchers = []
}
// 添加一个观察者
addWatcher (watcher) {
this.watchers.push(watcher)
}
// 删除一个观察者
removeWatcher (watcher) {
this.watchers = this.watchers.filter(item => item !== watcher)
}
// 通知所有观察者
notify (msg) {
this.watchers.forEach(watcher => {
watcher.update(msg)
})
}
}
// 观察者类
class Watcher {
constructor (name) {
this.name = name
}
// 收到通知后的处理
update (msg) {
console.log(this.name + ' => ' + msg)
}
// 订阅主题
addToSub (sub) {
sub.addWatcher(this)
}
}
let sub = new Subject()
let w1 = new Watcher('w1')
let w2 = new Watcher('w2')
w1.addToSub(sub)
w2.addToSub(sub)
sub.notify('hello world!')
用一个调度中心统一处理发布和订阅,下面是一个 js 版本的简单实现:
// 调度中心类
class Dispatch {
constructor () {
this.subscribers = {}
}
// 添加一个订阅
subscribe (type, fun) {
if (!this.subscribers[type]) this.subscribers[type] = [fun]
else this.subscribers[type].push(fun)
}
// 取消订阅
unsubscribe (type) {
this.subscribers[type] && delete this.subscribers[type]
}
// 发布消息
publish (type, msg) {
let target = this.subscribers[type]
target && target.length && target.forEach(fun => {
fun(msg)
})
}
}
let disp = new Dispatch()
disp.subscribe('type1', msg => { console.log(msg) })
disp.subscribe('type2', msg => { console.log(msg) })
disp.publish('type1', 'hello')
disp.publish('type2', 'world')
下面是一个 Vue 版本的简单实现
// EventBus.js
import Vue from 'vue'
export default new Vue()
// comp1.vue
EventBus.$on('test', v => {
console.log(v) // johnhan
})
// comp2.vue
EventBus.$emit('test', 'johnhan')