之前看公司一些大牛写的前台事件注册机制代码,总是似懂非懂,仔细研究才发现是观察者模式。
观察者模式
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
观察者模式主要解决一个对象状态的改变给其他对象通知的问题,并且代码易用性高,耦合度低。
观察者模式一般由主体和观察者两个对象组成,主体负责发布事件,观察者通过订阅事件来观察主体。其中最重要的是主体并不知道观察者的任何事情,即便观察者不存在,主体也可以独自存在并正常运行。而观察者知道主体,并能注册事件的回调函数。
自定义事件实现
事件应该具备的几个功能:
- 事件注册
- 事件执行
- 事件取消
/**
* 事件管理器
* @param {String} name 事件管理器名
*/
function EventManager(name){
//定义一个事件管理器名
this.name = name;
//eventLists 用于存储事件处理程序(观察者)
this.eventLists = [];
}
/**
* 注册事件
* @param {String} type 事件类型
* @param {Function} fun 事件处理函数
*/
EventManager.prototype.registerEvent = function(type,fun){
if(typeof this.eventLists[type] === 'undefined'){
this.eventLists[type] = [];
}
//把事件处理函数存储到eventLists列表中
this.eventLists[type].push(fun);
}
/**
* 执行注册事件
* @param {Object} event 事件
*/
EventManager.prototype.fireEvent = function(event){
if(!event.target){
event.target = this;
}
if(this.eventLists[event.type] instanceof Array){
const lists = this.eventLists[event.type];
lists.forEach((list)=>{
list(event);
})
}
}
/**
* 注销事件
* @param {String} type 事件类型
* @param {Function} fun 事件处理函数
*/
EventManager.prototype.removeEvent = function(type,fun){
if(this.eventLists[type] instanceof Array){
const lists = this.eventLists[type];
for(let i =0,len = lists.length;i < len;i++){
if(lists[i] === fun){
lists.splice(i,1);
break;
}
}
if(lists.length == 0){
delete this.eventLists[type];
}
}
}
使用自定义事件
function oparetion(event){
console.log('执行了该方法:' + event.message);
}
//创建一个事件处理器
var eventManager = new EventManager('love');
//注册一个happy事件
eventManager.registerEvent('happy',oparetion);
//执行happy事件
eventManager.fireEvent({type:'happy',message:'Love You'})//执行了该方法:Love You
//删除happy事件
eventManager.removeEvent('happy',oparetion);
仅触发一次的事件
/**
* 仅触发一次事件
* @param {String} type 事件类型
* @param {Function} fun 事件处理函数
*/
EventManager.prototype.one = function(type, fun){
var that = this;
//先注册一下事件
that.registerEvent(type, fun);
//再执行事件
that.fireEvent({type:type, message:'Love You Too'})
//最后移除事件
that.removeEvent(type, transfer);
}
原理就是先注册一下事件,再执行一次事件,执行完再取消事件。