+function(w) {
function Evt() {
return new Evt.prototype.init();
}
Evt.prototype = {
constructor: this,
init: function() {
this.handlers = {}
return this;
},
add: function(type, fn) {
if(typeof type === 'string' && !(type in this.handlers)) {
this.handlers[type] = []; //创建一个事件集
}
if(typeof fn === 'function') {
this.handlers[type].push(fn); //为当前事件注册函数
} else {
throw 'the method of argument not a function'
}
return this;
},
fire: function(type) {
var arrevt = [];
var args = [];
if(arguments.length > 2) {
args = Array.prototype.slice.apply(arguments, [1]); //获取事件参数
}else if(arguments.length > 1) {
args = arguments[1];
}
if(typeof type === 'string' && (type in this.handlers)) {
arrevt = this.handlers[type];
}
for(var i = 0, len = arrevt.length; i < len; i++) {
if(args.length > 0) {
//这里本想让事件触发扔到异步队列中去,然而却访问不到i了,
//于是这种操作被我弄得无意义了
+function(i) {
setTimeout(function() {
arrevt[i](args);
}, 0);
}(i);
}else {
+function(i) {
setTimeout(function() {
arrevt[i]();
}, 0);
}(i);
}
}
return this;
},
del: function(type, fn) {
if(typeof type === 'string' && (type in this.handlers)) {
if(typeof fn === 'function') {
var arrevt = this.handlers[type];
for(var i = 0, len = arrevt.length; i < len; i++) {
if(fn === arrevt[i]) {
arrevt.splite(i, 1); //删除该注册函数
break;
}
}
}
}
return this;
}
}
Evt.prototype.init.prototype = Evt.prototype;
window.evt = new Evt;
}(window);
以上代码将实现一个简单的pub/sub模式,一切皆事件,任何行为都是事件,使用方法
//将所要注册的方法交于一个类统一管理, 这里称为接口inf,
//这种写法略显"浮肿",但可通过bind创建函数并改变内部this指向
var inf = {
test: function(data) {
console.log(data);
}
}
//外部注册事件,并调用事件 传参仅支持数组或者对象
evt.add('test', inf.test).fire('test', 'hello, world');