为自定义对象添加自定义事件
由于javascript并没有自己的事件系统,借助于DOM的事件系统,如果只涉及到javascript对象就歇菜了。下面是一个仿制品,不要指望有事件冒泡这东西。
if(typeof Array.prototype.forEach !== "function"){
Array.prototype.forEach = function (fn, scope) {
for(var i=0,n=this.length>>>0;i<n;i++){
i in this && fn.call(scope,this[i],i,this)
}
}
}
var EventDispatcher = {
$A:function(iterable){
return Array.prototype.slice.call(iterable)
},
createEvents:function(){
this._listeners = {};
var names = this.events || [],name,type;
names.forEach(function(type){
name ="on"+ type.replace(/_([a-z])/g, function($1,$2){
return $2.toUpperCase()
}).replace(/^\w/, function (s) {
return s.toUpperCase();
});
if(typeof this[name] ==="undefined"){
this[name] = function(){
var args = this.$A(arguments);
return this.attachEvent.apply(this,[type].concat(args))
}
}
},this)
},
hasEvent:function(type){
return (this._listeners[type] instanceof Array && this._listeners[type].length > 0);
},
attachEvent:function(){
var args = this.$A(arguments),
type = args.shift(), callback = args.shift();
if (!this.hasEvent(type))
this._listeners[type] = [];
var listeners = this._listeners[type];
listeners.push({ callback:callback,args: args });
},
detachEvent:function(type,callback){
if (this.hasEvent(type)) {
var listeners = this._listeners[type],listener;
if(typeof callback === "undefined"){
delete this._listeners[type];
}else{
for(var i=0,n=listeners.length;i<n;i++){
if (listeners[i].callback === callback){
listeners.splice(i, 1);
return;
}
}
}
}
},
fireEvent:function(){
var args = this.$A(arguments),type = args.shift();
if (!this.hasEvent(type)) return ;
var listeners = this._listeners[type];
listeners.forEach(function(listener){
listener.callback.apply(this, listener.args.concat(args))
},this);
}
}
严格来说,这不能算一个类,应该叫接口的东西。当目标类实现它(把EventDispatcher的成员变成目标类的成员),并在原型中提供一个events的字符串数组成员后,我们调用了createEvents,它就拥有事件般的行为,由于没有了DOM的监控,我们需要fireEvent来触发事件。
一个例子:
var Person = function(name){
this.name = name
}
Person.prototype = {
events:["layout"]
}
var include = function(Concrete,Interface){//使用ruby式的命名方式,用于添加实例成员
for(var prop in Interface) {
Concrete.prototype[prop] = Interface[prop];
}
}
include(Person,EventDispatcher );
var p = new Person("司徒正美")
p.createEvents()
p.onLayout(function(name){
alert(name)
});
p.onLayout(function(name){
alert(name+"!!")
});
p.fireEvent("layout","参数")//依次弹出 "参数" "参数!!"
机器瞎学/数据掩埋/模式混淆/人工智障/深度遗忘/神经掉线/计算机幻觉/专注单身二十五年
浙公网安备 33010602011771号