事件对象
在触发DOM节点上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。
DOM中的事件对象
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>事件对象</title> 6 </head> 7 <body> 8 <div id="box"> 9 <input type="button" id="btn" value="button"> 10 </div> 11 </body> 12 </html>
在上边的页面中,点击<input>元素,以input-div-body-html-document的顺序冒泡。
封装一个事件处理程序,如下:
1 var event_util = { 2 //添加事件 3 addHandler: function(element, type, handler) { 4 if(element.addEventListener) { 5 element.addEventListener(type, handler, false); 6 } else if(element.attachEvent) { 7 element.attachEvent("on" + type, handler); 8 } else { 9 element["on" + type] = handler; 10 } 11 }, 12 //移除事件 13 removeHandler: function(element, type, handler) { 14 if(element.removeEventListener) { 15 element.removeEventListener(type, handler, false); 16 } else if(element.detachEvent) { 17 element.detachEvent("on" + type, handler); 18 } else { 19 element["on" + type] = null; 20 } 21 } 22 };
event对象包含与创建它的特定事件有关的属性和方法。
bubbles属性与stopPropagation()方法:
1 //表明事件是否冒泡 2 function bubbles(event) { 3 alert(event.bubbles); //true 4 }; 5 event_util.addHandler(btn, "click", bubbles); 6 // 阻止事件冒泡 7 function stopPropagation(event) { 8 event.stopPropagation(); 9 }; 10 event_util.addHandler(btn, "click", stopPropagation);
可以将事件处理程序与阻止事件冒泡写在一起;如:
1 function showMessage(event) { 2 alert("这个按钮不会冒泡!"); 3 event.stopPropagation(); 4 }; 5 event_util.addHandler(btn, "click", showMessage);
stopImmediatePropagation(),阻止事件的进一步捕获或者冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增);详情未知。
cancelable属性、preventDefault()方法与defaultPrevented()方法:
在html中新增一个<a>元素
1 <a href="http://www.baidu.com">百度</a>
1 //获取<a>元素 2 var link = document.getElementById("link"); 3 //表明是否可以取消事件的默认行为 4 function cancelable(event) { 5 alert(event.cancelable); //true 6 }; 7 event_util.addHandler(link, "click", cancelable); 8 //取消事件的默认行为 9 function preventDefault(event) { 10 event.preventDefault(); 11 }; 12 event_util.addHandler(link, "click", preventDefault); 13 //查询是否已经取消事件的默认行为 14 function defaultPrevented(event) { 15 alert(event.defaultPrevented); //true 16 }; 17 event_util.addHandler(link, "click", defaultPrevented);
取消默认行为之后,超链接将不能正常跳转到指定页面。
type属性,被触发事件的类型。
1 function type(event) { 2 alert(event.type); //"click" 3 }; 4 event_util.addHandler(btn, "click", type);
在需要通过一个函数来处理多个事件时,可以使用type属性。
1 var btn = document.getElementById("btn"); 2 function handler(event) { 3 switch(event.type) { 4 case "click": 5 alert("You‘ve clicked the button"); 6 break; 7 case "mouseover": 8 event.target.style.backgroundColor = "blue"; 9 break; 10 case "mouseout": 11 event.target.style.backgroundColor = ""; 12 break; 13 } 14 }; 15 event_util.addHandler(btn, "click", handler); 16 event_util.addHandler(btn, "mouseover", handler); 17 event_util.addHandler(btn, "mouseout", handler);
currentTarget属性,其事件处理程序当前正在处理事件的那个元素(事件处理程序挂载的那个元素)。
在事件处理程序内部,this对象的值始终等于currentTarget的值。
target属性,事件的目标。
如果直接将事件处理程序指定给目标元素,则this、currentTarget、target的值相同。
比较下面两种情况:
示例1:
1 function showCurrentTarget(event) { 2 alert(event.currentTarget); //object HTMLInputElement 3 }; 4 event_util.addHandler(btn, "click", showCurrentTarget); 5 6 function showTarget(event) { 7 alert(event.target); //object HTMLInputElement 8 }; 9 event_util.addHandler(btn, "click", showTarget);
示例2:
1 function showCurrentTarget(event) { 2 alert(event.currentTarget); //object HTMLBodyElement 3 }; 4 event_util.addHandler(document.body, "click", showCurrentTarget); 5 6 function showTarget(event) { 7 alert(event.target); //object HTMLInputElement 8 }; 9 event_util.addHandler(document.body, "click", showTarget);
事件处理程序指定给了document.body,所以currentTarget属性的值为document.body;
而target却指向<input>元素,因为它才是我们click的目标;由于按钮上并没有事件处理处理程序,冒泡到body上,在这里事件才得到处理。
也就是说,点了按钮,target就是按钮,但是按钮上并没有绑定事件,然后冒泡,冒到body上,body上有事件,currentTarget为body。
eventPhase属性,可以用来确定事件当前正位于事件流的哪个阶段。
如果是在捕获阶段调用的事件处理程序,则eventPhase值为1;如果事件处理程序处于目标对象上,则eventPhase值为2;如果是在冒泡阶段调用的事件处理程序,则evenPhase值为3.
1 btn.addEventListener("click", function(event) { 2 alert(event.eventPhase); //2 3 }, true); 4 btn.addEventListener("click", function(event) { 5 alert(event.eventPhase); //2 6 }, false); 7 8 document.body.addEventListener("click", function(event) { 9 alert(event.eventPhase); //1 10 }, true); 11 document.body.addEventListener("click", function(event) { 12 alert(event.eventPhase); //3 13 }, false);
事件的目标是按钮,所以按钮是处于目标阶段,不管以冒泡流还是捕获流,eventPhase值都是为2;当eventPhase值为2时,this、currentTarget和target是相等的。
对于document.body,当传入的参数为true,表示在捕获阶段调用事件处理程序,其evenPhase值为1;当传入的参数为false,表示在冒泡流调用的事件处理程序,其eventPhase值为3。
trusted属性,为true表示事件是浏览器生成的;为false表示事件是开发人员通过JS创建的(DOM3级事件中新增)。
1 function showMessage(event) { 2 alert("This is a button."); 3 alert(event.trusted); //undefined 4 }; 5 event_util.addHandler(btn, "click", showMessage);
event.trusted值为undefined,原因未明。
detail属性,与事件相关的细节信息;详情未知。
view属性,与事件关联的抽象视图;等同于发生事件的window对象;详情未知。
IE中的事件对象
要访问IE中的event对象有几种不同的方式,取决于指定事件处理程序的方法。
在使用DOM0级方法添加事件处理程序时,event对象作为window对象的的一个属性存在。
1 btn.onclick = function() { 2 var event = window.event; 3 alert(event.type); //"click" 4 };
如果事件处理程序是通过attachEvent()添加的,那么就会有一个event对象作为参数传入事件处理程序中。
1 btn.attachEvent("onclick", function(event) { 2 alert(event.type); //"click" 3 });
cancelBubble属性,默认值为false,将其设置为true,就可以阻止冒泡。
returnValue属性,默认值为true,将其设置为false,就可以取消事件的默认行为。
srcElement属性,事件的目标,与DOM中的target属性相同。
跨浏览器的事件对象
1 var event_util = { 2 //添加事件 3 addHandler: function(element, type, handler) { 4 if(element.addEventListener) { 5 element.addEventListener(type, handler, false); 6 } else if(element.attachEvent) { 7 element.attachEvent("on" + type, handler); 8 } else { 9 element["on" + type] = handler; 10 } 11 }, 12 //移除事件 13 removeHandler: function(element, type, handler) { 14 if(element.removeEventListener) { 15 element.removeEventListener(type, handler, false); 16 } else if(element.detachEvent) { 17 element.detachEvent("on" + type, handler); 18 } else { 19 element["on" + type] = null; 20 } 21 }, 22 //获取事件对象 23 getEvent: function(event) { 24 return event ? event : window.event; 25 }, 26 //获取事件目标 27 getTarget: function(event) { 28 return event.target || event.srcElement; 29 }, 30 //阻止事件冒泡 31 stopPropagation: function(event) { 32 if(event.stopPropagation) { 33 event.stopPropagation(); 34 } else { 35 event.cancelBubble = true; 36 } 37 }, 38 //取消事件默认行为 39 preventDefault: function(event) { 40 if(event.preventDefault) { 41 event.preventDefault(); 42 } else { 43 event.returnValue = false; 44 } 45 } 46 };