一、为什么要这么做?
在开发中我们不可避免需要使用到事件模型来进行交互,而我们面对的客户所使用浏览器是各种各样的,所以我们需要来进行兼容,我们主要面对的是两种事件模型:标准DOM2事件模型(现代标准浏览器)和IE事件模型(老版IE浏览器IE6~IE8),他们都给了我们绑定事件处理程序的方法;
- DOM2事件模型:使用addEvenListener(),它可以接受三个参数1.事件类型2.事件处理方法3.布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理;
- IE事件模型:使用attachEvent(),它可以接受两个参数1.事件处理函数名称,2.事件处理方法,
另外在触发某个事件的时候都产生一个事件对象event,这个对象会包含着与事件有关的信息,包括产生事件的元素、事件类型等相关信息。但是 DOM2事件模型和IE事件模型的事件对象的属性是不同的,如下: - DOM2事件模型事件模型的event对象:
属性/方法 | 类型 | Cool | 说明 |
---|---|---|---|
bubbles | Boolean | 只读 | 事件是否冒泡 |
cancelable | Boolean | 只读 | 是否可以取消事件的默认行为 |
currentTarget | Element | 只读 | 事件处理程序当前处理元素 |
detail | Integer | 只读 | 与事件相关细节信息 |
eventPhase | Integer | 只读 | 事件处理程序阶段:1 捕获阶段,2 处于目标阶段,3 冒泡阶段 |
preventDefault() | Function | 只读 | 取消事件默认行为 |
stopPropagation() | Function | 只读 | 取消事件进一步捕获或冒泡 |
target | Element | 只读 | 事件的目标元素 |
type | String | 只读 | 被触发的事件类型 |
view | AbstractView | 只读 | 与事件关联的抽象视图,等同于发生事件的window对象 |
- IE事件模型的even对象:
属性/方法 | 类型 | Cool | 说明 |
---|---|---|---|
cancelBubble | Boolean | 只读 | 默认为false,设置为true后可以取消事件冒泡 |
returnValue | Boolean | 只读 | 默认为true,设为false可以取消事件默认行为 |
srcElement | Element | 只读 | 事件的目标元素 |
type | String | 只读 | 被触发的事件类型 |
二、有哪些区别问题需要兼容?
目前来看主要来看需要解决五个问题:
- attachEvent()和addEvenListener()参数内容和不相同;
- 事件处理程序的作用域不相同,addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window。
- 为一个事件添加多个事件处理程序时,执行顺序不同,addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好。
三、如何做?
主要的区别找到了,该如何解决这些问题呢?这里我可以借鉴下jQuery创始人John Resig的做法代码如下:
function addEvent(node, type, handler) { //node参数为需要被绑定事件的元素;
//type是事件类型,handler是事件处理程序;
if (!node) return false; //如果没有这个元素 直接返回false
if (node.addEventListener) { //兼容标准DOM事件模型
node.addEventListener(type, handler, false);
return true;
}
else if (node.attachEvent) { //兼容IE事件模型
node['e' + type + handler] = handler;
node[type + handler] = function() {
node['e' + type + handler](window.event); //
};
node.attachEvent('on' + type, node[type + handler]);
return true;
}
return false;
}
另外在取消事件处理程序的时候,John Resig也给了我们一个很好的方法:
function removeEvent(node, type, handler) {
if (!node) return false;
if (node.removeEventListener) {
node.removeEventListener(type, handler, false);
return true;
}
else if (node.detachEvent) {
node.detachEvent('on' + type, node[type + handler]);
node[type + handler] = null;
}
return false;
}
网友评论