jRaiser揭秘――事件监听兼容处理
在事件监听处理方面,IE提供了attachEvent和detachEvent两个接口,而Firefox提供的是addEventListener和removeEventListener。最简单的兼容性处理就是封装这两套接口:
function addEvent(elem, eventName, handler) {
if (elem.attachEvent) {
elem.attachEvent(”on” + eventName, handler);
} else if (elem.addEventListener) {
elem.addEventListener(eventName, handler, false);
}
}
function removeEvent(elem, eventName, handler) {
if (elem.detachEvent) {
elem.detachEvent(”on” + eventName, handler);
} else if (elem.removeEventListener) {
elem.removeEventListener(eventName, handler, false);
}
}
然而,上面两个函数还没把问题完全解决。Firefox下,事件处理函数中的this指向被监听元素本身,而在IE下则不然。要解决这个问题,我首先想到的是prototype框架中的function.prototype.bind(下面简称bind):
function addEvent(elem, eventName, handler) {
if (elem.attachEvent) {
elem.attachEvent(”on” + eventName, handler.bind(elem));
} else if (elem.addEventListener) {
elem.addEventListener(eventName, handler, false);
}
}
这样做的结果是,再也无法移除事件处理函数。原因在于,移除事件处理函数时需要传入该函数的引用,而bind方法返回的是一个新函数而不是handler本身,且这个新函数的引用并没有保存下来。既然如此,只要把bind返回的引用给保存下来就好了。而存储结构就是个关键点。
首先,一个页面中有任意个元素,所以每个元素都要有一个集合,每个元素所有事件处理函数的引用就存放在这个集合中。
element.events = {};
其次,一个元素有多种事件(click、mouseover、mouseout等),同一个函数可以添加为多种事件的处理函数,所以每种事件的存储也必须是独立的。
elements.events.click = {};
element.events.mouseover = {};
…
最后,为每个事件处理函数添加一个唯一标识,以便在集合找到它。最简单的标识方法是数据库中常用的自动编号(递增)。
结合以上三点,编写一个生成事件代理的函数:
var eventId = 0;
function delegate(elem, eventName, handler) {
var events = elem.events = elem.events || {}, // 创建事件集合
id = handler.eventId = handler.eventId || ++eventId; // 生成事件标识
events[eventName] = events[eventName] || {}; // 创建某种事件的集合
var trueHandler = function(e) { // 真正被添加的事件处理函数
handler.call(elem, e);
};
events[eventName][id] = trueHandler; // 记下函数的引用
}
相对应地,还要写一个获取事件代理的函数:
function getDelegate(elem, eventName, handler) {
try { return elem.events[eventName][handler.eventId]; } catch (e) {}
}
这里用try…catch的原因是,避免elem.events和elem.events[eventName]未创建时出错。
最后addEvent和removeEvent改进如下:
function addEvent(elem, eventName, handler) {
handler = delegate(elem, eventName, handler);
if (elem.attachEvent) {
elem.attachEvent(”on” + eventName, handler);
} else if (elem.addEventListener) {
elem.addEventListener(eventName, handler, false);
}
}
function removeEvent(elem, eventName, handler) {
handler = getDelegate(elem, eventName, handler);
if (elem.detachEvent) {
elem.detachEvent(”on” + eventName, handler);
} else if (elem.removeEventListener) {
elem.removeEventListener(eventName, handler, false);
}
}
其实delegate函数中还可以做更多的事情,有兴趣者请自行研究jRaiser.event对象。
建议继续学习:
- 各种浏览器审查、监听http头工具介绍 (阅读:6253)
- 前端模板引擎 (阅读:3782)
- Js事件监听封装(支持匿名函数) (阅读:3598)
- jRaiser与jQuery的冲突问题 (阅读:2378)
- 在 JavaScript 中监听 IME 键盘输入事件 (阅读:2382)
- 提高短连接监听性能方法测试 (阅读:2237)
- jRaiser与jQuery的冲突问题 (阅读:1941)
- 社会化媒体:监听和衡量 (阅读:1993)
- Oracle 启动监听命令 (阅读:1746)
- 入门基础:浅析Oracle监听器安装与配置 (阅读:1742)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:mike 来源: 163 UED Team
- 标签: jRaiser 监听
- 发布时间:2010-05-17 13:08:38
- [55] IOS安全–浅谈关于IOS加固的几种方法
- [54] 图书馆的世界纪录
- [54] 如何拿下简短的域名
- [54] android 开发入门
- [52] Go Reflect 性能
- [52] Oracle MTS模式下 进程地址与会话信
- [49] 【社会化设计】自我(self)部分――欢迎区
- [48] 读书笔记-壹百度:百度十年千倍的29条法则
- [41] 程序员技术练级攻略
- [35] 视觉调整-设计师 vs. 逻辑