1.思路
(1)構思
var eventTarget = {
addEvent: function(){
//添加事件
},
fireEvent: function(){
//觸發事件
},
removeEvent: function(){
//移除事件
}
};
(2)建立一一對應的映射表
var eventTarget = {
//保存映射
handlers:{},
addEvent: function(){
//處理代碼
},
fireEvent: function(){
//觸發代碼
},
removeEvent: function(){
//移出代碼
}
};
(3)構建映射關系
handlers = {
"type1":[
"fun1",
"fun2",
// "..."
],
"type2":[
"fun1",
"fun2"
// "..."
]
//"..."
}
這樣每一個類型可以有多個處理函數,以便於我們以后擴充
(4)構建后
//直接量處理js自定義事件
var eventTarget = {
//保存事件類型,處理函數數組映射
handlers:{},
//注冊給定類型的事件處理程序,
//type -> 自定義事件類型, handler -> 自定義事件回調函數
addEvent: function(type, handler){
//判斷事件處理數組是否有該類型事件
if(eventTarget.handlers[type] == undefined){
eventTarget.handlers[type] = [];
}
//將處理事件push到事件處理數組里面
eventTarget.handlers[type].push(handler);
},
//觸發一個事件
//event -> 為一個js對象,屬性中至少包含type屬性,
//因為類型是必須的,其次可以傳一些處理函數需要的其他變量參數。(這也是為什么要傳js對象的原因)
fireEvent: function(event){
//判斷是否存在該事件類型
if(eventTarget.handlers[event.type] instanceof Array){
var _handler = eventTarget.handlers[event.type];
//在同一個事件類型下的可能存在多種處理事件,找出本次需要處理的事件
for(var i = 0; i < _handler.length; i++){
//執行觸發
_handler[i](event);
}
}
},
//注銷事件
//type -> 自定義事件類型, handler -> 自定義事件回調函數
removeEvent: function(type, handler){
if(eventTarget.handlers[type] instanceof Array){
var _handler = eventTarget.handlers[type];
//在同一個事件類型下的可能存在多種處理事件,找出本次需要處理的事件
for(var i = 0; i < _handler.length; i++){
//找出本次需要處理的事件下標
if(_handler[i] == handler){
break;
}
}
//刪除處理事件
_handler.splice(i, 1);
}
}
};
這是一種調用運行的方法
eventTarget.addEvent("eat",function(){
console.log(123); //123
});
eventTarget.fireEvent({type: "eat"});
這種方法有一個缺點,不能刪除該處理事件,因為我們是用映射表做的,而且也不提倡,直接給映射表里面存這么多數據,有點多。
另一種方法,將處理事件提取出來(推薦)
function b(){
console.log(123);
}
eventTarget.addEvent("eat",b);
eventTarget.fireEvent({
type: "eat"
}); //123
eventTarget.removeEvent("eat",b);
eventTarget.fireEvent({type: "eat"}); //空
也可以這樣,傳遞更多的參數
eventTarget.fireEvent({
type: "eat",
food: "banana"
});
function b(data){
console.log(data.food); //banana
}
(5)總結
//自定義事件構造函數
function EventTarget(){
//事件處理程序數組集合
this.handlers = {};
}
//自定義事件的原型對象
EventTarget.prototype = {
//設置原型構造函數鏈
constructor: EventTarget,
//注冊給定類型的事件處理程序,
//type -> 自定義事件類型, handler -> 自定義事件回調函數
addEvent: function(type, handler){
//判斷事件處理數組是否有該類型事件
if(typeof this.handlers[type] == 'undefined'){
this.handlers[type] = [];
}
//將處理事件push到事件處理數組里面
this.handlers[type].push(handler);
},
//觸發一個事件
//event -> 為一個js對象,屬性中至少包含type屬性,
//因為類型是必須的,其次可以傳一些處理函數需要的其他變量參數。(這也是為什么要傳js對象的原因)
fireEvent: function(event){
//模擬真實事件的event
if(!event.target){
event.target = this;
}
//判斷是否存在該事件類型
if(this.handlers[event.type] instanceof Array){
var handlers = this.handlers[event.type];
//在同一個事件類型下的可能存在多種處理事件,找出本次需要處理的事件
for(var i = 0; i < handlers.length; i++){
//執行觸發
handlers[i](event);
}
}
},
//注銷事件
//type -> 自定義事件類型, handler -> 自定義事件回調函數
removeEvent: function(type, handler){
//判斷是否存在該事件類型
if(this.handlers[type] instanceof Array){
var handlers = this.handlers[type];
//在同一個事件類型下的可能存在多種處理事件
for(var i = 0; i < handlers.length; i++){
//找出本次需要處理的事件下標
if(handlers[i] == handler){
break;
}
}
//從事件處理數組里面刪除
handlers.splice(i, 1);
}
}
};
// 調用方法
function b(){
console.log(123);
}
var target = new EventTarget();
target.addEvent("eat", b);
target.fireEvent({
type: "eat"
}); //123
.
