事件模型
注册事件
W3C:
addEventListener: 接受三个参数,第一个参数是事件名称(没有"on"前缀,如"click"),第二个是事件处理函数,第三个为布尔值,true表示开启捕获,false表示开启冒泡。
1 可以为同一个目标DOM节点注册不同的事件
var div1 = document.getElementById("myDiv"); div1.addEventListener("click", func1, false); div1.addEventListner("mouse", func2, false);
2 可以为同一个目标节点的相同事件设置不同的事件处理函数
var div1 = document.getElementById("myDiv"); div1.addEventListener("click", func1, false); div1.addEventListner("click", func2, false);
这种情况下,W3C并没有规定那个事件处理函数先执行,但在火狐上测试,按照注册顺序执行。
3 如果有多个相同的事件注册在同一目标上,而且参数相同,那么事件监听器只被调用一次,忽略重复情况
var div1 = document.getElementById("myDiv"); div1.addEventListener("click", func1, false); div1.addEventListner("click", func1, false);
这种情况下,只执行一次事件处理函数
4 this指的是触发事件的DOM节点
IE:
attachEvent: 接受两个参数,第一个参数是事件名称(必须包含前缀"on", 如"onclick"),第二个参数是事件处理函数。IE中事件传播方式总是冒泡方式。
1 第一点和W3C相同
2 对于第二点,IE8中是先注册的后执行
3 对于第三点,IE8中会都执行,并不会忽略
4 对于第四点,IE8中的this指的是window全局对象。
下面再看一种情况:
<html> <head> <script type = "text/javascript"> function test() { var div1 = document.getElementById("div"); /* div1.attachEvent("onclick", function() {alert(1);}); div1.attachEvent("onclick", function() {alert(2);}); div1.attachEvent("onclick", function() {alert(3);}); */ div1.addEventListener("click", function() {alert(1);},false); div1.addEventListener("click", function() {alert(2);},false); div1.addEventListener("click", function() {alert(3);},false); /*将onclick属性注册的事件拿到最下面*/ div1.onclick = function() { alert(4); } } </script> </head> <body onload = "test()"> <div id = "div">WOSHI</div> </body> </html>
上面用onclick属性注册了一个事件,在火狐中的执行结果: 1-2-3-4, 在IE8中的执行结果: 4-3-2-1
<html> <head> <script type = "text/javascript"> function test() { var div1 = document.getElementById("div"); /*将onclick属性注册的事件拿到最上面*/ div1.onclick = function() { alert(4); } div1.attachEvent("onclick", function() {alert(1);}); div1.attachEvent("onclick", function() {alert(2);}); div1.attachEvent("onclick", function() {alert(3);}); /* div1.addEventListener("click", function() {alert(1);},false); div1.addEventListener("click", function() {alert(2);},false); div1.addEventListener("click", function() {alert(3);},false); */ } </script> </head> <body onload = "test()"> <div id = "div">WOSHI</div> </body> </html>
在火狐中是4-1-2-3,在IE8中是4-3-2-1.
上面的结果说明,用属性注册的事件,在火狐中顺序没有影响,仍然是谁先注册,谁先执行,而在IE8中,以属性注册事件先于用attachEvent注册的事件执行
解除事件
W3C:
removeEventListener: 接受的参数同addEventListener
IE:
detachEvent: 接受的参数同attachEvent。
事件对象
在W3C模型中事件对象只有在事件触发的时候才作为参数传给事件处理函数,而IE中事件对象是window的一个属性
取消冒泡
W3C:
event.stopPropagation(): event为事件对象
IE
event.cancelBubble:event为事件对象
阻止默认事件
W3C:
event.preventDefault(): event为事件对象
IE:
event.returnValue = false: event为事件对象
Target和srcElement
W3c用target属性指明触发事件的原始DOM节点,而IE中用的是srcElement属性
button属性
W3C:
0 左键
1 中键
2 右键
IE:
1 左键
2 中键
4 右键
并且这3个数字总共有8中组合:
0 没有键按下
1 左键
2 中键
3 左键+中键
4 右键
5 左键+右键
6 中键+右键
7 左键+中键+右键
对于W3C和IE的button属性,只有在mousedown和mouseup事件中才能得到正确的值。对于click事件,在FF中点击左键可以得到正确的值,而在IE中 不能
clientX和clientY
W3C和IE中均有这个属性,这里他们没有分别。他们指的是鼠标相对于页面可见区域的位置,即使页面发生了滚动,如果把鼠标放到同一位置,得到的仍然是同一个值:
页面滚动前:
页面滚动后:
红色方框显示鼠标位置,鼠标两次都位于页面可见区域的左上角,不管页面是否滚动,显示的值一样。
pageX,pageY和x, y
FF中用pageX和pageY来指定鼠标相对于整个文档(不是可见区域)的位置,这就是说,如果页面发生了滚动,即使鼠标位于网页上可见区域的同一位置,所得的结果不同。IE8以及更早版本没有相应的属性,但是可以根据滚动信息以及上面介绍的客户区坐标计算:
var event = window.event; var pageX = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft); var pageY = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop);
滚动前
滚动后:
红色方显示鼠标相对于整个文档的位置,虽然两次都位于页面可见区域左上角,但是高度值不一样。
which和keyCode
FF中获取按下的键盘值用which,IE中用keyCode