我正在开发一个跨浏览器的事件处理系统。我请一些开发人员查看我的代码。其中一位开发人员说我的实现是基于回调而不是真实事件。有什么区别?
为方便起见,我在下面提供了我的实现的源代码(以及as a gist)。到目前为止,我没有发现任何问题。它适用于我测试过的所有浏览器。
我很抱歉这个问题的描述不好,我不熟悉那个纯粹的事件部分。
var evento = (function (window) {
var win = window
, doc = win.document
, _handlers = {}
, addEvent
, removeEvent
, triggerEvent;
addEvent = (function () {
if (typeof doc.addEventListener === "function") {
return function (el, evt, fn) {
el.addEventListener(evt, fn, false);
_handlers[el] = _handlers[el] || {};
_handlers[el][evt] = _handlers[el][evt] || [];
_handlers[el][evt].push(fn);
};
} else if (typeof doc.attachEvent === "function") {
return function (el, evt, fn) {
el.attachEvent(evt, fn);
_handlers[el] = _handlers[el] || {};
_handlers[el][evt] = _handlers[el][evt] || [];
_handlers[el][evt].push(fn);
};
} else {
return function (el, evt, fn) {
el["on" + evt] = fn;
_handlers[el] = _handlers[el] || {};
_handlers[el][evt] = _handlers[el][evt] || [];
_handlers[el][evt].push(fn);
};
}
}());
// removeEvent
removeEvent = (function () {
if (typeof doc.removeEventListener === "function") {
return function (el, evt, fn) {
el.removeEventListener(evt, fn, false);
Helio.each(_handlers[el][evt], function (fun) {
if (fun === fn) {
_handlers[el] = _handlers[el] || {};
_handlers[el][evt] = _handlers[el][evt] || [];
_handlers[el][evt][_handlers[el][evt].indexOf(fun)] = undefined;
}
});
};
} else if (typeof doc.detachEvent === "function") {
return function (el, evt, fn) {
el.detachEvent(evt, fn);
Helio.each(_handlers[el][evt], function (fun) {
if (fun === fn) {
_handlers[el] = _handlers[el] || {};
_handlers[el][evt] = _handlers[el][evt] || [];
_handlers[el][evt][_handlers[el][evt].indexOf(fun)] = undefined;
}
});
};
} else {
return function (el, evt, fn) {
el["on" + evt] = undefined;
Helio.each(_handlers[el][evt], function (fun) {
if (fun === fn) {
_handlers[el] = _handlers[el] || {};
_handlers[el][evt] = _handlers[el][evt] || [];
_handlers[el][evt][_handlers[el][evt].indexOf(fun)] = undefined;
}
});
};
}
}());
// triggerEvent
triggerEvent = function (el, evt) {
_handlers[el] = _handlers[el] || {};
_handlers[el][evt] = _handlers[el][evt] || [];
for (var _i = 0, _l = _handlers[el][evt].length; _i < _l; _i += 1) {
_handlers[el][evt][_i]();
}
};
return {
add: addEvent,
remove: removeEvent,
trigger: triggerEvent,
_handlers: _handlers
};
}(this));
答案 0 :(得分:2)
我不关心你的系统是基于回调,事件还是lambda-calculus。对于你在这里曝光的那一点,它似乎写得很好,并承诺做得很好(虽然我很好奇你如何处理removeEvent()
;)。
但是,我对您的实施有一些评论:
我很惊讶每次他们打算给他们打电话时接受检查物业存在的人数。在函数调用过程中没有人会将你的IE换成FF(任何愚蠢到足以定义document.addEventListener
属性而非实际的ECMA-5替换的人都应该被鞭打到死,如果你问我),因此,请检查您在开始时使用的平台并完成它,如下所示:
if (doc.addEventListener) {
addEvent = // ...
freeEvent = // ...
}
else if (doc.attachEvent) {
addEvent = // ...
freeEvent = // ...
}
/* etc. */
例如,在IE8中,事件的目标将无法以与ECMA-5惯例相同的方式获得。
如果要提供真正的跨浏览器界面,则应为事件处理程序提供统一的执行上下文。 这可能包括&#34;取消&#34;功能将转化为:
cancel = function (e) { e.returnValue = false; }; // IE8-
cancel = function (e) { e.preventDefault(); }; // ECMA-5
你还应该将this
恢复到IE8-下的目标对象,并统一target
和event.target
语义。
如果你真的想对程序员好一点,你也可以解决一些奇怪的问题,比如
可能还有其他几个。
我为自己的目的而做的方式是在实际处理程序周围生成一个包装器,它可以处理所有平台的特性,并在调用实际的用户代码之前建立一致的执行上下文。
最后一句话:除了它的美丽,我不太确定它是否仍然需要支持Netscape4风格的事件。但这是一个信仰问题,所以...