/**
* 事件总线类
*
* @example
*
* var ev = new eventbus()
*
* // 绑定事件
* ev.on('test',()=>{
* console.log('执行测试方法')
* })
* ev.emit('test') // 触发事件
* ev.off('test') // 取消事件
*
*
*/
class eventbus {
// 事件侦听器
_listener = {}
// 默认忽略事件名称大小写
_ignoreCase = true
/**
* 监听当前实例上的自定义事件。事件可以由 emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
* @param {String} event 事件名称
* @param {Function} fn 回调函数
* @returns {eventbus} 返回当前事件对象
*/
on(event, fn) {
if (typeof event === "string" && typeof fn === "function") {
event = this._ignoreCase ? event.toLowerCase() : event
if (this._listener[event]) {
this._listener[event].push(fn);
} else {
this._listener[event] = [fn];
}
}
return this;
}
/**
* 监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。
* @param {String} event 事件名称
* @param {Function} fn 回调函数
* @returns {eventbus} 返回当前事件对象
*/
once(event, fn) {
if (typeof event === "string" && typeof fn === "function") {
event = this._ignoreCase ? event.toLowerCase() : event
var wrapper = function (event, fn) {
return function (...args) {
fn.apply(this, args)
this.off(event, wrapper)
}
}(event, fn)
this.on(event, wrapper)
}
return this;
}
/**
* 移除自定义事件监听器。
*
* 如果没有提供参数,则移除所有的事件监听器;
*
* 如果只提供了事件,则移除该事件所有的监听器;
*
* 如果同时提供了事件与回调,则只移除这个回调的监听器
* @param {String} event 事件名称
* @param {Function} fn 回调函数
* @returns {EventTarget} 返回当前事件对象
*/
off(event, fn) {
if (typeof event === "string" && typeof fn === "function") {
event = this._ignoreCase ? event.toLowerCase() : event
var key = event
// 如果同时提供了事件与回调,则只移除这个回调的监听器
this._listener[key] = this._listener[key] && this._listener[key].filter(f => f !== fn)
} else if (typeof fn === "function") {
// 如果只提供了事件,则移除该事件所有的监听器;
for (var key in this._listener) {
this._listener[key] = this._listener[key] && this._listener[key].filter(f => f !== fn)
}
} else {
// 如果没有提供参数,则移除所有的事件监听器;
this._listener = {}
}
return this;
}
/**
* 触发当前实例上的事件。附加参数都会传给监听器回调。
* @param {String} eventName 事件名称
* @param {Array} args 参数
* @returns {eventbus} 返回当前事件对象
*/
emit(eventName) {
if (eventName && this._listener[eventName]) {
eventName = this._ignoreCase ? eventName.toLowerCase() : eventName
var length = this._listener[eventName].length
for (var start = 0; start < length; start++) {
var fn = this._listener[eventName][start];
if (fn !== null && fn !== undefined)
fn.apply(this, [...arguments].slice(1));
}
}
return this;
}
}
export default eventbus