1. 事件流
1.IE的事件流是事件冒泡流。 Netscape 的事件流是事件捕获流。
2.IE的事件冒泡:即事件开始是由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档)。 如 由 div body html document 从左到右进行。
3.事件捕获:意思是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。 如:document html body div 顺序进行。
2.事件处理程序
响应某个事件的函数就叫事件处理程序或事件侦听器。事件处理程序的名字以“on”开头。
1/ html事件处理程序
形式如下:
<input type="button" value="Click me" onclick="alert('clicked')" />
<input type="button" value="click" onclick="showMessage()" />
2/ DOM0级事件处理程序
就是将一个函数赋值给一个事件处理程序属性。这些属性通常都小写。
var btn=document.getElementById("DOMTest"); btn.onclick=function(){ alert(this.id); } btn.onclick=null; //在加载时就已经执行了这条,所以上面的onclick事件就执行不了了
3/ DOM2级事件处理程序
DOM2级事件 定义了两个方法。用于处理指定和删除事件处理程序的操作:addEventListener() 和removeEventListener()。
var btn=document.getElementById("DOMTest"); btn.addEventListener("click",function(){ alert(this.id); },false); btn.addEventListener("click", function(){ alert(this.nodeName); },false); //顺序输出: DOMTest BUTTON //而要删除这两个事件处理程序时,直接添加下面的代码是没有用的 //虽然看似使用了相同的参数,但实际上第二个参数与传入addEventListener() //中的那个是完全不同的函数 btn.removeEventListener("click",function(){ alert("removeEventListener 取消事件") },false)
使用removeEventListener()的正确方法应是:
var btn=document.getElementById("DOMTest"); var hander=function(){ alert(this.id); } btn.addEventListener("click",hander,false); btn.removeEventListener("click",hander,false); //上面的直接不执行了
4/ IE事件处理程序
IE中实现DOM中类似的两个方法:attachEvent()和detachEvent()
var btn=document.getElementById("DOMTest"); var id="window"; btn.attachEvent("onclick",function(){ alert(this.id); //输出全局中的变量window })
attachEvent的第一个参数是”onclick“
在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。在使用DOM0级方法时,事件处理程序会在其所属元素的作用域内运行。在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window。
在ie8及以下这些处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。
var btn=document.getElementById("DOMTest"); //var id="window"; btn.attachEvent("onclick",function(){ alert("world"); //输出全局中的变量window }) btn.attachEvent("onclick",function(){ alert("hello"); }) //在ie8下顺序显示hello world。 //在ie9及以上顺序显示world hello
使用attachEvent()添加的事件可以通过detachEvent()来移除,条件是必须提供相同的参数,与DOM方法一样,这意味着添加的匿名函数将不能被移除。
5/ 跨浏览器的事件处理程序
var btn=document.getElementById("DOMTest"); var EventUtil={ 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(type,handler); }else{ element["on"+type].handler; } } }; //调用 var handler=function(){alert(this.nodeName)} EventUtil.addHandler(btn,"click",handler); //EventUtil.removeHandler(btn,"click",handler);
输出结果是: chrome及IE9+中输出 BUTTON, IE8输出indefind;
3.事件对象
1./ DOM中的事件对象
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。
event包含的属性和方法:
type:被触发事件的类型
currentTarget:其事件处理程序当前正在处理事件的那个元素。
target:事件的目标。
preventDefault():取消事件的默认行为。
stopPropagation()取消事件的进一步捕获或冒泡。
在事件处理程序内部,对象this始终等于currentTarget的值。而target则只包含事件的实际目标。
如果像DOM0级那样直接将事件处理程序指定给了目标元素,则this,currentTarget,target三个的值一样。
但如果将事件处理程序存在于按钮的父节点中,则这些值则不相同。
var btn=document.getElementById("DOMTest"); document.body.onclick=function(event){ alert(event.currentTarget===document.body); alert(this===document.body); alert(event.target===btn); } //弹出结果分别是true true true
在上面this和currentTarget都等于document.body ,因为事件处理程序是注册在这个元素上,而target元素却等于按钮元素。因为它是click事件真正的目标。click事件冒泡到了document.body,在那里事件才得到了处理。
2/ IE中的事件对象
与访问DOM中的event对象不同,要访问IE中的event对象有几种不同的方法,取决于指定事件处理程序的方法。在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。
var btn=document.getElementById("DOMTest"); btn.onclick=function(event){ //var event=window.event; alert(event.type); } //弹出click,如果去掉var event=window.event;则ie8会报错:无法获取未定义或 null 引用的属性“type”
even包含的属性和方法:
cancelBubble:与stopPropagation()方法作用相同。取消冒泡事件。默认为falue
returnValue:与preventDefault()方法作用相同。默认为true
srcElement:与target相同。事件的目标。
type:被触发事件的类型。
因为事件处理程序的作用域是根据指定它的方式来确定的,所以不能认为ithis会始终等于事件目标,故而,还是使用event.srcElement比较好。如下:
var btn=document.getElementById("DOMTest"); btn.onclick=function(event){ alert(window.event.srcElement===this); } btn.attachEvent("onclick",function(event){ alert(event.srcElement===this); }) //结果返回: true false
3/ 跨浏览器的事件对象
var btn=document.getElementById("DOMTest"); var EventUtil={ 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; } }, getEvent:function(event){ return event ? event : window.event; }, getTarget:function(event){ return event.target || event.srcElement; }, 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(type,handler); }else{ element["on"+type].handler; } }, stopPropagation:function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble=true; } } }; //调用 EventUtil.addHandler(btn,"click", function(event){ event=EventUtil.getEvent(event); alert("clci"); })
浙公网安备 33010602011771号