为了以跨浏览器的方式处理事件,不少开发人员会使用能够隔离浏览器差异的javascript库,本文从事件处理程序、事件对象差异出发,演示开发最适合的事件处理方法
基本名词解析:
事件
|
用户或浏览器自身执行的某种动作
|
事件流
|
从页面中接收事件的顺序,,IE的事件流指的是事件冒泡流,而Netscape Communicator的事件流是事件捕获流
|
事件冒泡
|
事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)
|
事件捕获
|
不太具体的节点应该更早接收到事件,而最集体的节点应该最后接收到事件
|
事件处理程序
|
响应某个事件处理的函数(或事件侦听器) |
事件流包括的三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段
![](http://images0.cnblogs.com/i/601481/201408/132112505921745.png)
事件处理程序
事件处理程序名称
|
说明
|
添加事件
|
删除事件
|
DOM0级
|
将一个函数赋值给一个事件处理程序属性。
|
//使用javascript指定事件处理程序,首先必须取得一个要操作的对象应用
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert(this.id);
};
|
var removeBtn = document.getElementById("myRemoveBtn");
removeBtn.onclick = function(){
btn.onclick = null;
};
|
DOM2级
|
用于处理指定和删除事件处理程序操作的方法:addEventListener()和removeEventListener(),接受3个函数:处理的事件名,作为事件处理程序的函数和一个布尔值(true捕获阶段,false冒泡阶段) |
var btn = document.getElementById("myBtn");
var handler = function(){
alert(this.id);
};
btn.addEventListener("click", handler, false);
|
var removeBtn = document.getElementById("myRemoveBtn");
removeBtn.onclick = function(){
btn.removeEventListener("click", handler, false); //大多数情况下,将事件处理函数添加到事件流的冒泡阶段,这样最大限度兼容各种浏览器
};
|
IE事件处理程序
|
实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。接受两个参数:事件处理程序名称与事件处理程序函数
|
var btn = document.getElementById("myBtn");
var handler = function(){
alert("Clicked");
};
btn.attachEvent("onclick", handler);
|
var removeBtn = document.getElementById("myRemoveBtn");
removeBtn.onclick = function(){
btn.detachEvent("onclick", handler);
};
|
另外还有一种HTML事件处理程序,不推荐使用。
<input type="button" value="Click Me" onclick="alert("Clicked")" />
<script type="text/javascript">
function showMessage(){
alert("Hello world!");
}
</script>
因为它存在如下缺点:
1,不同javascript引擎遵循的标识符解析规则略有差异,很有可能会在访问非限定对象成员时出错。
2,HTML和javascript代码紧密耦合,如果要更换事件处理程序需要改动HTML和javascript代码
var EventUtil = { /* 参数说明: element:要操作的对象 type:事件名称 handler:事件处理程序函数 */ addHandler: function(element, type, handler){ if (element.addEventListener){ element.addEventListener(type, handler, false); } else if (element.attachEvent){ element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } }, removeHandler: function(element, type, handler){ if (element.removeEventListener){ element.removeEventListener(type, handler, false); } else if (element.detachEvent){ element.detachEvent("on" + type, handler); } else { element["on" + type] = null; } } };
使用演示
var btn = document.getElementById("myBtn"); var handler = function(){ alert("Clicked"); }; EventUtil.addHandler(btn, "click", handler); var removeBtn = document.getElementById("myRemoveBtn"); EventUtil.addHandler(removeBtn, "click", function(){ EventUtil.removeHandler(btn, "click", handler); });
在触发DOM上的某个事件是,会产生一个世家对象event,这个对象中包含所有与事件有关的信息。
包括导致事件的元素(DOM中event.currentTarget,event.target,this;IE中window.event.srcElement或event.srcElement,this),事件类型(event.type)和其他与事件相关的信息
我们经常使用event.preventDefault()取消其默认行为。另外,stopProgation()方法用于立即停在事件在DOM层次中的传播,即取消进一步的事件捕获或冒泡
需要通过一个函数处理多个事件,可以使用type属性
var btn = document.getElementById("myBtn"); var handler = function(event){ switch(event.type){ case "click": alert("Clicked"); break; case "mouseover": event.target.style.backgroundColor = "red"; break; case "mouseout": event.target.style.backgroundColor = ""; break; } }; btn.onclick = handler; btn.onmouseover = handler; btn.onmouseout = handler;
虽然DOM和IE中的event对象不同,但基于它们之间的相似性依旧可以拿出跨浏览器的方案。
var EventUtil = { /* 功能说明:绑定事件 参数说明: element:要操作的对象 type:事件名称 handler:事件处理程序函数 */ addHandler: function(element, type, handler){ if (element.addEventListener){ element.addEventListener(type, handler, false); } else if (element.attachEvent){ element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } }, /* 函数说明:鼠标按钮。 主鼠标按钮被单击时触发click事件 DOM的button属性: 0:主鼠标按钮 1:中间鼠标(滚轮) 2:次鼠标按钮 但对于IE8及之前版本button属性很大差异 */ getButton: function(event){ if (document.implementation.hasFeature("MouseEvents", "2.0")){ return event.button; } else { switch(event.button){ case 0: case 1: case 3: case 5: case 7: return 0; case 2: case 6: return 2; case 4: return 1; } } }, /* 函数说明:键盘与文本事件 IE8及其他版本和Opere是keyCode中保存字符 其他主流浏览器支持一个char Code属性,发生在keypress事件 */ getCharCode: function(event){ if (typeof event.charCode == "number"){ return event.charCode; } else { return event.keyCode; } }, getClipboardText: function(event){ var clipboardData = (event.clipboardData || window.clipboardData); return clipboardData.getData("text"); }, getEvent: function(event){ return event ? event : window.event; }, getRelatedTarget: function(event){ if (event.relatedTarget){ return event.relatedTarget; } else if (event.toElement){ return event.toElement; } else if (event.fromElement){ return event.fromElement; } else { return null; } }, getTarget: function(event){ return event.target || event.srcElement; }, /* 函数说明:鼠标滚轮事件 */ getWheelDelta: function(event){ if (event.wheelDelta){ return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta); } else { return -event.detail * 40; } }, /* 函数说明:取消其默认行为 */ preventDefault: function(event){ if (event.preventDefault){ event.preventDefault(); } else { event.returnValue = false; } }, /* 函数说明:解绑事件 */ removeHandler: function(element, type, handler){ if (element.removeEventListener){ element.removeEventListener(type, handler, false); } else if (element.detachEvent){ element.detachEvent("on" + type, handler); } else { element["on" + type] = null; } }, setClipboardText: function(event, value){ if (event.clipboardData){ event.clipboardData.setData("text/plain", value); } else if (window.clipboardData){ window.clipboardData.setData("text", value); } }, /* 函数说明:立即停在事件的传播,即取消进一步的事件捕获或冒泡 */ stopPropagation: function(event){ if (event.stopPropagation){ event.stopPropagation(); } else { event.cancelBubble = true; } } };