说在开始,Javascript自定义事件类似设计的观察者模式,通过状态的变更来监听行为,主要功能解耦,易于扩展。多用于组件、模块间的交互。
原型模式下的js自定义事件
var EventTarget = function() {
this._listener = {};
};
EventTarget.prototype = {
constructor: this,
addEvent: function(type, fn) {
if (typeof type === "string" && typeof fn === "function") {
if (typeof this._listener[type] === "undefined") {
this._listener[type] = [fn];
} else {
this._listener[type].push(fn);
}
}
return this;
},
addEvents: function(obj) {
obj = typeof obj === "object"? obj : {};
var type;
for (type in obj) {
if ( type && typeof obj[type] === "function") {
this.addEvent(type, obj[type]);
}
}
return this;
},
fireEvent: function(type) {
if (type && this._listener[type]) {
//event参数设置
var events = {
type: type,
target: this
};
for (var length = this._listener[type].length, start=0; start<length; start+=1) {
//改变this指向
this._listener[type][start].call(this, events);
}
}
return this;
},
fireEvents: function(array) {
if (array instanceof Array) {
for (var i=0, length = array.length; i<length; i+=1) {
this.fireEvent(array[i]);
}
}
return this;
},
removeEvent: function(type, key) {
var listeners = this._listener[type];
if (listeners instanceof Array) {
if (typeof key === "function") {
for (var i=0, length=listeners.length; i<length; i+=1){
if (listeners[i] === key){
listeners.splice(i, 1);
break;
}
}
} else if (key instanceof Array) {
for (var lis=0, lenkey = key.length; lis<lenkey; lis+=1) {
this.removeEvent(type, key[lenkey]);
}
} else {
delete this._listener[type];
}
}
return this;
},
removeEvents: function(params) {
if (params instanceof Array) {
for (var i=0, length = params.length; i<length; i+=1) {
this.removeEvent(params[i]);
}
} else if (typeof params === "object") {
for (var type in params) {
this.removeEvent(type, params[type]);
}
}
return this;
}
};
测试demo
var myEvents = new EventTarget();
myEvents.addEvents({
"once": function() {
alert("该弹框只会出现一次!");
this.removeEvent("once");
},
"infinity": function() {
alert("每次点击页面,该弹框都会出现!");
}
});
document.onclick = function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
if (!target || !/input|pre/i.test(target.tagName)) {
myEvents.fireEvents(["once", "infinity"]);
}
};
实现类似jquery$符号
用doucment.createEvent创建事件,initEvent初始化,dispatchEvent发射事件
var $ = function(el) {
return new $.init(el);
};
$.init = function (el) {
this.el = (el && el.nodeType == 1)? el: document;
};
$.init.prototype = {
constructor: this,
addEvent: function(type, fn, capture) {
var el = this.el;
if (window.addEventListener) {
el.addEventListener(type, fn, capture);
var ev = document.createEvent("HTMLEvents");
ev.initEvent(type, capture || false, false);
if (!el["ev" + type]) {
el["ev" + type] = ev;
}
} else if (window.attachEvent) {
el.attachEvent("on" + type, fn);
if (isNaN(el["cu" + type])) {
// 自定义属性
el["cu" + type] = 0;
}
var fnEv = function(event) {
if (event.propertyName == "cu" + type) { fn.call(el); }
};
el.attachEvent("onpropertychange", fnEv);
if (!el["ev" + type]) {
el["ev" + type] = [fnEv];
} else {
el["ev" + type].push(fnEv);
}
}
return this;
},
fireEvent: function(type) {
var el = this.el;
if (typeof type === "string") {
if (document.dispatchEvent) {
if (el["ev" + type]) {
el.dispatchEvent(el["ev" + type]);
}
} else if (document.attachEvent) {
el["cu" + type]++;
}
}
return this;
},
removeEvent: function(type, fn, capture) {
var el = this.el;
if (window.removeEventListener) {
el.removeEventListener(type, fn, capture || false);
} else if (document.attachEvent) {
el.detachEvent("on" + type, fn);
var arrEv = el["ev" + type];
if (arrEv instanceof Array) {
for (var i=0; i<arrEv.length; i+=1) {
el.detachEvent("onpropertychange", arrEv[i]);
}
}
}
return this;
}
};
测试demo
var fnClick = function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
if (target.nodeType === 1) {
alert("点击类型:" + e.type);
$(target).fireEvent("alert");
}
}, funAlert1 = function() {
alert("自定义alert事件弹出!");
}, funAlert2 = function() {
alert("自定义alert事件再次弹出!");
};
// 测试用的张小姐图片
var elImage = document.getElementById("image");
$(elImage)
.addEvent("click", fnClick)
.addEvent("alert", funAlert1)
.addEvent("alert", funAlert2);
// 删除自定义事件按钮
var elButton = document.getElementById("button");
$(elButton).addEvent("click", function() {
$(elImage)
.removeEvent("alert", funAlert1)
.removeEvent("alert", funAlert2);
alert("清除成功!");
});
参数 | 事件 | 初始化方法 |
---|---|---|
HTMLElements | HTMLEvent | initEvent() |
MouseEvents | MouseEvent | initMouseEvent() |
UIEvents | UIEvent | initUIEvent() |
来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]