持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
引言
发布订阅与观察者模式是js设计模式里的一种,也是很常见,使用率极高的一种设计模式。在vue.js中这两种设计模式也是它的一个核心。
此文先讲解使用原理,并手动实现,在总结区别
发布订阅模式
分三个核心点:
- 订阅者
- 发布者
- 信号中心/事件中心
发布订阅模式有一个统一的信号中心,由订阅者向里面投递自己的信号,当需要执行任务时,发布者就会向信号中心的每一个信息发送通知,然后各自开始执行自己的任务。发布者不用管信号中心有没有信号,信号是谁
通俗理解就是,订阅者(用户)下单买东西,发布者(老板)生产货物后,就看有没有订单,有订单就发送
代码实现:
// 事件触发器
class EventEmitter{
// 构造函数创建信息中心
constructor(){
this.subs = Object.create(null)
}
// 注册事件 判断如果有该信息事件,就继续追加,反之加入信息事件
$on(eventType, handler){
this.subs[eventType] = this.subs[eventType] || []
this.subs[eventType].push(handler)
}
// 触发事件 触发时执行每一个信息事件里存储的函数
$emit(eventType){
if(this.subs[eventType]){
this.subs[eventType].forEach(f => f())
}
}
}
var em = new EventEmitter()
// 订阅者注册信息事件
em.$on('click',() => console.log('click1'))
em.$on('click',() => console.log('click2'))
// 发布者执行信息事件
em.$emit('click')
执行结果,打印出click1 和 click2
观察者模式
分两个核心点:
- 观察者 -- watcher对象
包含update方法:当事件发生时,具体要做的事情 - 发布器 -- dep
包含subs数组:存储所有的观察者
包含addSub方法:用于添加观察者
包含notify方法:当事件触发时,调用所有观察者的update方法
注意:没有信号中心
观察者模式是没有一个统一的调度中心,观察者需要直接将自己注册到发布器中去,一旦事件触发,发布器就会挨个执行每个watcher观察者对象里的update方法,达到通知的效果
代码实现:
// 发布器
class Dep{
constructor(){
this.subs = [] // 记录所有的观察者
}
// 添加观察者
addSub(sub){
// 判断存在并且必须有update方法
if(sub && sub.update){
this.subs.push(sub)
}
}
// 发布通知 挨个执行每个观察者的update方法
notify(){
this.subs.forEach(sub => sub.update())
}
}
// 观察者
class Watcher{
update(){
console.log('update')
}
}
var dep = new Dep()
var watcher = new Watcher()
dep.addSub(watcher)
dep.notify()
执行结果,打印出:update
总结
区别:
发布/订阅模式 有统一调度中心调用,因此发布者和订阅者不需要知道对方的存在
观察者模式 是由具体的发布器调度,比如当事件触发,Dep 就会去调用观察者的方法,所以观察者模
式的观察者与发布器之间是存在依赖关系的

往期精彩文章
🌟webpack 手写插件流程
🌟两种方式轻松做react css样式隔离
🌟彻底理解redux的中间件原理
🌟canvas实现刮刮奖效果
🌟前端实现pdf下载
🌟web前端性能优化(全汇总)
🌟一句话概括this指向问题
🌟MutationObserver 实现微任务原理分析
🌟遇到几次的大厂笔试题:装饰数组push方法
🌟V8垃圾回收策略与GC算法
🌟浏览器缓存策略(强缓存和协商缓存)
🌟$nextTick 源码解读与原理分析
🌟手动封装适合react hook使用的状态管理工具