实现一个最小版本的vue —— 基本概念:发布订阅者和观察者的区别(一)

77 阅读3分钟

一、发布订阅者模式

  • 订阅者
  • 发布者
  • 信号中心(事件中心) 存在一个信号中心,某个任务执行完成,就向信号中心发布一个信号,其他任务可以向信号中心订阅这个信号,从而知道什么时候自己可以开始执行,这就叫发布订阅者模式。

1. vue兄弟组件传值 理解发布订阅者模式 3个角色

// eventBus.js文件:事件中心
let eventBus = new Vue()

// 组件A文件:发布者
addTodofunction(){
  // 发布消息
  eventBus.$emit('add-todo',params)
}

// 组件B文件:订阅者
created(){
  // 订阅消息
  eventBus.$on('add-todo',function(){})
}

2. 发布订阅者的实现(信号中心)

class myEventEmitter {
  constructor() {
    // eventMap 用来存储事件和监听函数之间的关系
    this.eventMap = {};
  }

  // type 这里就代表事件的名称  订阅事件
  on(type, handler) {
    // hanlder 必须是一个函数,如果不是直接报错
    if (!(handler instanceof Function)) {
      throw new Error("哥 你错了 请传一个函数");
    }
    
    this.eventMap[type] = this.eventMap[type] || [];

    this.eventMap[type].push(handler);
  }

  emit(type, params) { // 发布事件
    if (this.eventMap[type]) { // 处理事件(触发)
      this.eventMap[type].forEach((handler, index) => {
        handler(params);
      });
    }
  }

  off(type, handler) {
    if (this.eventMap[type]) {
      this.eventMap[type].splice(this.eventMap[type].indexOf(handler) >>> 0, 1);
    }
  }
}
  • 代码测试
const myEvent = new myEventEmitter();
const testHandler = function (params) {
  console.log(`test事件被触发了,testHandler 接收到的入参是${params}`);
};
myEvent.on("test", testHandler); 
myEvent.emit("test", "newState");

二、观察者模式

观察者模式没有事件中心,只有发布者和订阅者,发布者需要知道订阅者的存在。在观察者模式中订阅者又叫做观察者。

  1. 观察者(订阅者) -- Watcher
  • update():当事件发生时,具体要做的事情(例如:更新视图),是由发布者调用的
  1. 发布者(目标)-- Dep(记录所有的订阅者,当事件发生时通知所有订阅者)
  • subs数组: 存储所有的观察者
  • addSub(): 添加观察者
  • notify(): 当事件发生,调用所有观察者的update()方法

1. 观察者模式

Dep dependency依赖: 收集依赖

// 发布者-目标
class Dep {
  constructor(){
    // 记录所有的订阅者
    this.subs = []
  }
  // 添加订阅者
  addSub(sub){
    if(sub && sub.update){ // 必须包含update方法
      this.subs.push(sub)
    }
  }
  // 发布通知 触发所有订阅者的update
  notify(){
    this.subs.forEach(sub => {
      sub.update()
    })
  }
}

// 订阅者-观察者
class Watcher {
  update(){
    console.log('update')
  }
}
  • 测试
let dep = new Dep()
let watcher = new Watcher()
dep.addSub(watcher) // 订阅
dep.notify() // 发布

三、区别

观察者没有事件中心。

  • 发布订阅者模式由统一调度中心调度,因此订阅者和发布者不知道对方的存在。
  • 观察者模式是由具体目标调度,比如当事件触发,Dep发布者就会去调用观察者的方法,所以观察者的订阅者与发布者之间存在依赖的。

观察者

当发布者Dep中数据发生变化的时候,会调用自己的notify方法通知所有的订阅者(调用订阅者Watcher的update方法),订阅者Watcher需要调用Dep的addSub方法订阅。发布者Dep内部记录了所有的观察者(subs),发布者和订阅者之间存在相互依赖的关系。

发布订阅者

多了一个事件中心,通过 事件中心隔离了发布者和订阅者。兄弟组件之间的传值。