什么是发布订阅模式?

简单说发布订阅模式(也可以叫作观察者模式)是定义对象间的一种一对多的依赖关系,当一个对象状态发生变化时,所有依赖于他的对象都将得到通知

而且 JS 天生对发布订阅支持

我们都知道 vue 的响应式就是依赖发布订阅模式 + Object.defineProperty() / Proxy

其实在我们平时写代码时,也会经常用到,比如下面的一段代码

1
2
3
document.addEventListener("click", () => {
console.log("click")
})

就像 document 给们订阅了 click 事件的机会,当我们触发 click 后,就是通知 js 去执行我们的回调
而且还可以通过 removeEventListener 取消订阅

发布订阅模型

  • 发布者会给订阅者提供一个方法以方便订阅某些事情要发生时要做的事情
  • 发布者可以通过触发一些操作来告知订阅者订阅已来到,可以做对应的后续处理
  • 当订阅者不想再订阅的时候可以进行订阅的取消

手写一个发布订阅模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Observer {
obj = {}
on = function (name, callback) {
if (!this.obj[name]) {
this.obj[name] = [callback]
} else {
this.obj[name].push(callback)
}
}

trigger = function (name) {
const sub = this.obj[name] || []
sub.forEach(v => v())
}

remove = function (name, fn) {
const sub = this.obj[name] || []
const index = sub.findIndex(el => fn === el)
if (index > -1) {
sub.splice(index, 1)
}
}
}

const even = new Observer()

const listener = () => {
console.log("onClick")
}

even.on("click", listener)
even.on("click", () => {
console.log("onHandle")
})
even.trigger("click")
even.remove("click", listener)
even.trigger("click")

// 输出:onClick onHandle onHandle