日期:2014-05-16  浏览次数:20432 次

javascript中onclick在各种浏览器下的差异

在Dom Level1中没有定义事件模型,在Dom Level2中定义了事件模型一个较小的子集,在Dom Level3(2004)中事件才被完整定义。
?? ???? 由于IE还没有对于Dom Level1的完整支持,所以当前的浏览器主要存在IE和DOM两种不同的事件模型。这直接导致了事件处理成为JS跨浏览器编程中差异最大的部分。还好除 了IE之外,Mozilla FireFox、Opera、Safari都统一实现了Dom Level2定义的事件模型。
?? ???? 本文尝试总结关于事件处理的所有相关要点,包括添加删除事件、得到事件对象、得到触发事件的对象、捕获和冒泡事件流、终止事件流、阻止某个事件的默认行为等等。

一、添加事件的方式
1.写在HTML元素标签内:
<div onclick="clk()" id="testDiv">click me!</div>
<script>
?? function clk(){
?? ???? alert(1);
?? }
</script>
2.JS得到页面元素后直接指定:
<script>
?? var oDiv = document.getElementById("testDiv");
?? oDiv.onclick = clk;
?? //或者
?? oDiv.onclick = function(){
?? ???? alert(1);
?? }
</script>
3.JS为一个元素的一个事件添加多个处理函数:
<script>
?? var oDiv = document.getElementById("testDiv");
//for IE
?? oDiv.attachEvent("onclick",clk);
?? oDiv.detachEvent("onclick",clk);
//for DOM(FireFox,Opera..)
?? oDiv.addEventListner("click",clk,false)
?? oDiv.removeEventListner("click",clk,false)
</script>

注意:
1.对于Dom中增删事件处理函数的第三个boolean参数稍后解释,一般情况下false就好了。
2.在第2、3种方法中,指定事件处理函数为clk而不能写成clk(),任何方法在任何位置其后加上()表示对这个方法的一次运行。这也造成了对于添加的事件处理方法无法添加参数,只能是一个无参数调用。
3.第3种方法中,IE的事件名称一"on"开头如"onclick",而Dom的事件类型没有如"click"。
4.另外强调一点,使用document.getElementById("testDiv");这样的语句最好要在页面文档完全载入之后 (window.onload内,后续方法掉用内),至少要在这个Div的定义之下,浏览器对于页面文件的解释顺序这里不详细叙述。只是强调一下严重性, 例如这段代码,<div id="testDiv"><script>var oDiv = document.getElementById("testDiv");</script></div>对于IE来讲是致命 的,很可能你会得到一个系统进程错误,然后所有IE窗口消失。

二、如何得到事件对象
对于IE:事件对象是全局对象,window.event就可以得到这个对象
对于Dom:事件根据添加事件处理函数的方法不同而略有区别。
相对上面提到的第2,3中添加事件的方法,浏览器会隐式自动把event作为事件处理函数传给处理函数,通过arguments[0]可以得到。
而对于第1种方法需要这样写<div onclick="clk(event)" id="testDiv">click me!</div>需要将event作为clk的一个参数传回来,为了和其他事件添加保持一致处理方便,建议将其作为第一个参数。
这样我们就可以通过一句话来处理浏览器差异:
var oEvent = window.event?window.event:arguments[0];

三、如何得到触发事件的元素
当我们获得事件对象oEvent之后我们希望得到触发这个事件的页面元素
对于IE:oEvent.srcElement
对于DOM:oEvent.target
同样写成一句话:oSrc = oEvent.srcElement?oEvent.srcElement:oEvent.target;

虽然很简单,这里还是需要有些细节需要特别注意的:
?? ???? 对于这样的一段HTML<div onclick="clk(event)" id="outerDiv"><div id="innerDiv">testSrc</div></div>??
?? ???? 虽然onclick事件是attach到outerDiv上的,但是当你点击文字"testSrc"触发事件并通过上面那句话得到的oSrc并不是outerDiv,而是实际触发的对象。
?? ???? 更特别的是,对于实际触发事件的对象在IE和DOM两种模型下还有所不同,因为Dom标准中文本节点可以触发事件的而IE不可以,所以在IE下oSrc是 innerDiv(oSrc.nodeType==1),而在Dom下oSrc是内容为"testDiv"的文本节点 (oSrc.nodeType==3)。
?? ???? 这会造成一定的困扰,当你的目标想要得到outerDiv时,建议使用这种写法:<div onclick="clk(event,this)" id="outerDiv"><div id="innerDiv">testSrc</div></div>这样,你甚至可以不去理会event对象,而事件处 理函数传入的this即是指向outerDiv的指针。
?? ???? 当然这只是针对第1种添加事件的方法而言,而针对不可以传入参数的第2,3种添加事件方法则没有什么好办法,一直向上查找parentNode直到找到为止吧。

这里可以看出三种添加事件的方法是各有短长的,根据实际情况来选择应用吧。

四、事件对象还包含哪些信息
这块儿的东西我最不喜欢写,东西挺多浏览器差异大我记住的很少。
把我用比较多的列出来,而且基本上这些各个浏览器是一致的。
oEvent.type 事件类型 click、mouseover等等
oEvent.clientX oEvent.clientY 鼠标事件触发的坐标(相对于浏览器窗口)
oEvent.screenX oEvent.screenY 鼠标时间触发的坐标(相对于屏幕)
oEvent.keyCode 键盘事件按键代码
oEvent.altKey oEvent.ctrlKey oEvent.shiftKey 事件发生时alt、ctrl、shift键是否按下