发布订阅模式
$ 定义
基于一个自定义事件通道,收集与之相关的订阅成员,通过发布自定义事件的方式通知各个订阅成员。
$ Vue中的语法
// Vue 自定义事件
let vm = new Vue()
// 注册事件(订阅消息)
vm.$on('dataChange', () => {
console.log('')
})
vm.$on('dataChange', () => {
console.log('dataChange1')
})
// 触发事件(发布消息)
vm.$emit('dataChange')
// dataChange dataChange1
如上所示,收集之后的订阅成员关系可以简单理解为{ 'dataChange': [fn1, fn2]}
.vue通过on
注册事件,通过emit
发布时间.其实就是循环调用了对象中key值对应的数组中的方法.
$ 模拟发布订阅
经过分析我们已经知道了收集者是一个对象,注册事件是通过$on
,发布事件是通过$emit
.那么我们先简单实现这个类.
// 事件触发器
class EventEmittter {
constructor() {
this.subscribe = Object.create(null)
}
//注册事件
$on(enentType, hander) {}
//触发事件
$emit(enentType) {}
}
注意这里的subscribe
就是定义中说的自定义事件通道.创建对象可以用到Object.create(null)
,通过它创建出来的对象是没有原型的,可以提高性能.
on注册事件
$on(enentType, hander) {
this.subscribe[enentType] = this.subscribe[enentType] || []
this.subscribe[enentType].push(hander)
}
如上enentType
是自定义事件名,hander
是该自定义事件下的订阅成员.他们被收集到了subscribe中.
emit发布事件
通过传入的自定义事件名去发布对应订阅成员.
$emit(enentType) {
if (this.subscribe[enentType]) {
this.subscribe[enentType].forEach(hander => {
hander();
});
}
}
测试
let em = new EventEmittter();
em.$on('click', () => {
console.log('click111');
})
em.$on('click', () => {
console.log('click222');
})
em.$emit('click');// click111 click222