小二,上酒!
天涯的渡口, 一人陪马儿清瘦, 多么富有, 天下了心中。
发布订阅模式
我们在项目中使用的事件总线$Bus其实就是发布订阅模式,还有一个和它很像的观察者模式
我们在vue项目中可能这样使用Bus来兄弟组件通信
//Bus.js
import Vue from 'vue'
const Bus = new Vue();
export default Bus;
//组件1
import Bus from './Bus';
//注册事件 可以写在mounted生命周期中
Bus.$on('add',(val)=>{
console.log(val);
//逻辑
})
//组件2
import Bus from './Bus'
//触发事件 可以在methods的逻辑方法中
Bus.$emit('add',100)
//组件3
import Bus from './Bus'
//触发事件 可以在methods的逻辑方法中
Bus.$emit('add',200)
用法很简单,用$on去订阅,$emit去触发发布,$emit会回调所有(该名称)用$on注册的回调方法
接下来我们去实现一个简单的Bus
Bus实现代码
//事件中心
class Bus{
//事件队列对象
queue = {};
//订阅方法
$on(name,fn){
//先判断当前注册事件名称是否存在,存在直接等于自身,不存在等于[];
this.queue[name] = this.queue[name]? this.queue[name] : [];
//添加到对应数组
this.queue[name].push(fn)
}
//触发发布方法
$emit(name,...args){
//如果不存在该订阅数组 直接return
if(!this.queue[name]){
return;
}
//循环回调函数数组执行回调函数
this.queue[name].forEach(fn=>{
fn(...args)
})
}
//取消订阅方法
$off(name,fn){
//如果不存在该订阅数组 直接return
if(!this.queue[name]){
return;
}
//这里相当于做了删除操作 过滤当前的方法fn
this.queue[name] = this.queue[name].filter(f=>f!==fn)
}
//再来一个只被触发一次的方法
$ones(name,fn){
//自定义一个回调方法
const cb = (...args)=>{
//在回调方法中调用注册时传进来的方法
fn.call(this,...args);
//执行完删除当前回调方法,下次回调列表中就没有该回调了
this.$off(name,cb)
}
//先判断当前注册事件名称是否存在,存在直接等于自身,不存在等于[];
this.queue[name] = this.queue[name]? this.queue[name] : [];
//添加到对应数组
this.queue[name].push(cb)
}
}
好啦, 几个方法都写完了, 下面我们就来测试一下
测试
$on和$emit的使用
const bus = new Bus();
//回调函数
const bF = (v)=>{
console.log(v)
}
//注册事件1
bus.$on('a',(v)=>{
console.log(v)
})
//注册事件2
bus.$on('a',bF)
//触发事件
bus.$emit('a','hello Bus')
//控制台输出两次hello Bus
$off的使用
const bus = new Bus();
//回调函数
const bF = (v)=>{
console.log(v,'---------')
}
//注册事件1
bus.$on('a',(v)=>{
console.log(v)
})
//注册事件2
bus.$on('a',bF)
//取消注册事件2的回调方法
bus.$off('a',bF)
//触发事件
bus.$emit('a','hello Bus')
//控制台只输出一次hello Bus
$ones的使用
const bus = new Bus();
//回调函数
const bF = (v)=>{
console.log(v,'---------')
}
//注册事件1
bus.$on('a',(v)=>{
console.log(v)
})
//注册事件2
bus.$ones('a',bF)
//触发事件
bus.$emit('a','hello Bus')
//再次触发
bus.$emit('a','hello Bus two')
//注册事件2只被回调一次 输出hello Bus ---------
//注册事件1被回调2次 输出hello Bus 和 hello Bus two
最后
上面代码都没有做类型判断,如typeof === 'function',理解和会用就好,实际使用可以自己加一下,我又偷个懒,哈哈~
做人和写代码我都不太喜欢复杂的东西,总想着能不能简单点。