首先,我们先想想一个事件收发器需要有什么样的功能? 简单来说需要以下三个功能:
1、注册事件监听功能
2、移除事件监听功能
3、触发事件功能
我们先自定义一个事件收发器对象EventBus:
1、包含_event属性,用来存储事件与对应的处理函数;
2、包含$on和$once方法用来注册事件监听
3、包含$remove方法用来移除事件监听
4、包含$emit方法用来触发事件
var EventBs = {
_event: {},
$on: function(event, fn){},
$once: function(event, fn){},
$off: function(event, fn){},
$emit: function(){event}
}
我们先来说说$on的实现逻辑:
/**
* event是自定义事件名
* fn是对应的处理函数
*/
$on: function(event, fn){
// 一个事件可以同时绑定多个处理函数
this._event[event] = this._event[event] || []
this._event[event].push(fn)
}
我们再说说$once方法,$once的作用是只绑定一次,第二次触发事件不会再执行处理函数。
/**
* 先调用$on绑定事件处理函数handler,然后在handler里面调用$off方法移除事件监听
* event是自定义事件名
* fn是对应的处理函数
*/
$once: function(event, fn){
var _this = this
function on () {
// 移除监听,然后再执行回调函数。这样就实现了只触发一次的功能
_this.$off(event, on)
fn.apply(_this, arguments)
}
this.$on(event, on)
}
既然$once里面说到了$off方法,我们就来说说$off方法:
/**
* event是自定义事件名
* fn是对应的处理函数
*/
$off: function(event, fn){
var _this = this
// 如果不传入任何参数,解绑所有事件
if (!arguments.length) {
this._events = {}
}
// 解绑指定事件的所有处理函数
if (!fn) {
this._events[event] = null
}
var cbs = this._events[event]
// 遍历删除对应处理函数
var cb
var i = cbs.length
while (i--) {
cb = cbs[i]
if (cb === fn) {
cbs.splice(i, 1)
break
}
}
}
最后我们来看一下事件触发函数$emit:
$emit: function(event){
var cbs = this._events[event]
// toArray理解为自定义的一个数组话方法(将类数组对象转化为数组的方法)
const args = toArray(arguments, 1)
for (var i = 0, l = cbs.length; i < l; i++) {
cbs[i].apply(vm, args)
}
}
到此为止,我们已经实现了一个比较简单的事件收发器,重要是理解这个实现思维。