什么是发布-订阅模式?
发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到状态改变的通知。
- 订阅者(Subscriber):把自己想订阅的事件 注册 到调度中心
- 当发布者 发布该事件到调度中心,也就是该事件触发时,由 调度中心 统一调度订阅者注册到调度中心的处理代码
手写发布订阅模式
发布订阅模式,他的核心内容只有四个:
- 缓存列表 message
- 向消息队列中添加 订阅事件 $on
- 删除消息队列的 订阅事件 $off
- 触发消息队列的 订阅事件 $emit
创建一个 Observer 类
我们先创建一个 Observer 类
class Observer {
}
在 Observer 类里,需要添加一个构造函数:
class Observer {
constructor() {
}
}
添加三个核心方法
还需要添加三个方法,也就是我们前面讲到的 on、emit、off 方法,为了让这个方法长得更像 Vue,我们需要在这几个方法前面都加上 $,即
- 向消息队列中添加 订阅事件 $on
- 删除消息队列中的 订阅事件 $off
- 触发消息队列中的 订阅事件 $emit
class Observer{
constructor() {
}
//向消息队列中添加 订阅事件
$on() {}
//删除消息队列中的 订阅事件
$off() {}
//触发消息队列中的 订阅事件
$emit() {}
}
设置缓存列表
我们前面所讲到的缓存列表(消息队列),即是调度中心了。
class Observer {
constructor() {
this.message = {} //消息队列
}
}
实现 $on 方法
给 $on() 方法传入两个参数:
- type:事件名(事件类型)
- callback:回调函数
- 在添加 订阅事件 之前,我们需要判断 消息队列 中,是否已经存在该 订阅事件。
- 如果没有这个属性,就初始化一个空的数组
- 如果有这个属性,就它的后面push一个 新的 callback。
class Observer {
constructor() {
this.message = {};
}
$on(type, callback) {
if(!this.message[type]) {
this.message[type] = [];
}
this.message[type].push(callback);
}
$off() {}
$emit() {}
}
实现 $off 方法
$off 方法用来删除消息队列里的内容
- $off(type) :表示删除整个 type 事件
- $off(type, callback) :表示删除 type 事件中的某个消息
class Observer {
constructor() {
this.message = {};
}
$on(type, callback) {
if(!this.message[type]) {
this.message[type] = [];
}
this.message[type].push(callback);
}
$off(type, callback) {
if(!this.message[type]) return;
if(!callback) this.message[type] = undefined
this.message[type] = this.message[type].filter(item => item !== callback);
}
}
实现 $emit 方法
$emit 用来触发消息队列里的内容:
- 该方法需要传入一个 type 参数,用来确定哪一个事件
- 主要流程就是对这个 type 事件做一个轮询(for循环),挨个执行每一个消息的回调函数 callback 就可以了
class Observer {
constructor() {
this.message = {};
}
$on(type, callback) {
if(!this.message[type]) {
this.message[type] = [];
}
this.message[type].push(callback);
}
$off(type, callback) {
if(!this.message[type]) return;
if(!callback) this.message[type] = undefined
this.message[type] = this.message[type].filter(item => item !== callback);
}
$emit(type) {
if(!this.message[type]) return
this.message[type].forEach((item) => {
item();
})
}
}
案例使用
class Observer {
constructor() {
this.message = {};
}
$on(type, callback) {
if(!this.message[type]) {
this.message[type] = [];
}
this.message[type].push(callback);
}
$off(type, callback) {
if(!this.message[type]) return;
if(!callback) this.message[type] = undefined;
this.message[type] = this.message[type].filter((item) => item !== callback);
}
$emit(type) {
if(!this.message[type]) return
this.message[type].forEach(item => {
item();
});
}
}
let person = new Observer();
function buy() {
console.log('buy');
}
function walk() {
console.log('walk');
}
person.$on('buy', buy);
person.$on('walk', walk);
person.$off('walk', walk);
person.$emit('buy');
console.log(person);