起因
在拼多多面试时,面试官问了下Vue中的组件数据传递方式,我就提到了EventBus,不过之前并没有仔细研究,当时写的版本也问题很多。因此回来之后又重新整理了下。如果有错误或者问题,希望大家可以指出来
// EventBus构造函数
function EventBus(){
this.listeners = {} //保存已经注册的事件
}
// 判断是否为函数
function isFunction(fn) {
return fn && Object.prototype.toString.call(fn)=== '[object Function]'
}
// 判断是否为字符串
function isString(str) {
return str && (typeof(str) === 'string' || Object.prototype.toString.call(str)=== '[object String]')
}
function isValid(event, callback) {
return isString(event) && isFunction(callback)
}
// 监听事件的方法
EventBus.prototype.$on = function(event, callback) {
if (isValid(event, callback)) { //校验参数合法性
if (this.listeners[event] && !this.listeners[event].includes(callback)) { // 已经注册过该事件的话,将callback加入到该事件的回调数组中
this.listeners[event].push(callback)
} else {
this.listeners[event] = [callback] // 若之前没有监听过该事件,则初始化为一个数组
}
} else {
console.error('参数不合法或已存在')
}
}
// 触发已经注册过的事件
EventBus.prototype.$emit = function(event, params) {
if (isString(event) && this.listeners[event]) {
this.listeners[event].forEach(cb => { // 将该事件上所有的回调函数都执行一次
cb(params)
})
}
}
// 移除某事件对应的回调函数
EventBus.prototype.$remove = function(event, callback) {
if (isValid(event, callback) && this.listeners[event]) {
let index = this.listeners[event].indexOf(callback)
if (index !== -1) {
this.listeners[event].splice(index, 1)
}
}
}
// demo
var eb = new EventBus()
const cb = function(params){
console.log('add ', params)
}
eb.$on('add', cb)
eb.$emit('add', 123)
// 打印 'add 123'
eb.$remove('add', cb)
console.log(eb)
//打印
// EventBus {
// listeners: {
// 'add': []
// }
// }