// 我们需要一个event对象,拥有on、remove、emit方法
var event = (function () {//采用闭包是用来存储注册的事件eventObjs
eventObjs = {};
return {
/**注册事件,可以连续注册,可以注册多个事件*/
on: function (type, handler) {
// 如果注册过对应type事件,就直接把handler加在队列中,如果没有对应type类型,就先创建一个type类型的队列(数组),然后再handler添加进去
// 不得不说,这代码很漂亮
(eventObjs[type] || (eventObjs[type] = [])).push(handler);
},
/**移除事件,
* -如果没有参数,移除所有事件,
* -如果只带有 事件名 参数,就移除这个事件名下的所有事件,
* -如果带有事件名 参数和事件处理函数名,那么久表示移除对应事件名下的某一个处理事件,
*/
remove: function (type, handler) {
if (arguments.length === 0) {//没有参数,移除所有事件
eventObjs = {};
} else if (arguments.length === 1) {//说明只有type:事件的类型,要移除此事件名下的所有处理函数
eventObjs[type] = [];
} else if (arguments.length === 2) {//移除type事件的handler函数
// 使用循环移除所有的 该函数 对应的 type事件
let _events = eventObjs[type];
if (!_events) return;
// 因为移除意向后,数组长度会自动变短,倒着循环,数组的序号不会受到影响
for (let i = _events.length - 1; i >= 0; i--) {
if (_events[i] === handler) {
_events.splice(i, 1);
}
}
}
},
/**发射事件,触发事件,包装参数,传递给事件处理函数*/
emit: function (type) {
let args = Array.prototype.slice.call(arguments, 1);//拿到arguments从1开始后的所有参数,返回的是数组
let _events = eventObjs[type];
if (!_events) return;
for (let i = 0; i < _events.length; i++) {
// 如果要绑定上下文,就需要用到call或apply
_events[i].apply(null, args);
}
},
}
})();
使用方式
console.log(1);
event.on('click',() => console.log("第一个click事件"));
console.log(2);
event.on('click',() => console.log("第二个click事件"));
console.log(3);
event.emit('click');
console.log(4);
运行结果