观察者模式
在 DOM 上绑定事件处理函数addEventListener就是观察者模式最典型的用法,但观察者和被观察者之间还存在耦合,被观察者还是知道观察者的。
class Theme {
constructor(public name: string) {}
private state: number = 0
private observerList: Observer[] = []
getState(): number {
return this.state
}
setState(state: number): void {
this.state = state
this.observerList.forEach((observer) => {
observer.update(this)
})
}
addObserver(observer: Observer): void {
this.observerList.push(observer)
}
}
class Observer {
constructor(public name: string) {}
update(theme: Theme): void {
console.log(`${this.name} ${theme.name} update ${theme.getState()}`)
}
}
const theme = new Theme('dark')
const observer1 = new Observer('observer1')
const observer2 = new Observer('observer2')
theme.addObserver(observer1)
theme.addObserver(observer2)
theme.setState(1)
theme.setState(2)
发布-订阅模式
发布 - 订阅模式 中的发布者和订阅者不需要知道对方的存在,他们通过消息中心来进行通信,解耦更加彻底,Vue 有一套这样的事件机制,比如 EventBus。在多层组件的事件处理中,如果你觉得一层层 $on、$emit 比较麻烦,而你又不想用 Vuex,那么可以使用 EventBus 来解决组件间的数据通信。
interface saveEventObiect {
[key: string]: Function[]
}
class EventEmitter {
private events: saveEventObiect = {}
on(name: string, fn: Function) {
this.events[name] = this.events[name] || []
if (fn) this.events[name].push(fn)
}
emit(name: string, ...args: any[]) {
if (this.events[name]) {
this.events[name].forEach((fn) => fn.apply(this, args))
}
}
off(name: string) {
this.events[name] = []
}
}
const emitter = new EventEmitter()
emitter.on('save', (a: any, b: any, c: any) => {
console.log('save')
console.log(a, b, c)
})
emitter.on('save', () => {
console.log('save2')
})
emitter.emit('save', 'aa', 'bb', 'cc')