假设有以下HTML代码:html
<!DOCTYPE html> <html> <head> <title>Event</title> </head> <body> <div id="myDiv">Click me</div> </body> </html>
其DOM树以下图所示:浏览器
若是点击div元素,由于div是该DOM树中层次最深的节点,那么哪一个节点先接收事件?是由浅到深,仍是由深到浅?函数
事件流描述的是从页面中接收事件的顺序。
存在两种事件流:事件冒泡(IE)和事件捕获(Netscape)(这两种事件流的事件传播顺序以下图所示)this
“DOM2级事件”规定的事件流包括三个阶段:spa
仍以上面的例子为例,单击div元素的事件触发顺序以下图所示:code
事件是用户或浏览器自身执行的某种动做(好比click、load、mouseover等)
事件处理程序(事件侦听器)是响应某个事件的函数。
事件处理程序的名字以“on”开头,如click事件的事件处理程序是onclick。htm
为事件指定处理程序的方式有如下几种:对象
可使用HTML为元素指定事件处理程序,方法是:为元素添加一个与事件处理程序同名的属性,该属性的值是可以执行的JS代码或JS函数。blog
//直接定义JS代码 <input type="button" value="点击" onclick="alert('clicked')" /> //调用在页面其余地方定义的JS函数 <input type="button" value="点击" onclick="showMessage()" />
以上代码为按钮添加了鼠标单击事件(click)的事件处理程序(onclick)。seo
注:这样定义的事件处理程序在执行时,有权访问全局做用域中的任何代码
IE九、Firefox、Safari、Chrome和Opera支持DOM2级事件处理程序
var btn = document.getElementById("myBtn"); //为按钮指定onclick事件处理程序 btn.onclick = function(){ alert("Clicked"); }
注:
将事件处理程序属性的值设置为null便可删除事件处理程序:
btn.onclick = null;
“DOM2级事件”定义了两个方法来处理事件处理程序:
addEventListener(要处理的事件名,事件处理程序函数,布尔值)
var btn = document.getElementById("myBtn"); btn.addEventListener("click", function(){ alert(this.id); }, false);
注:
经过addEventListener()添加的事件处理程序只能经过removeEventListener()删除,且删除时传入的参数必须与添加时传入的参数相同。
可是经过addEventListener()添加的匿名函数没法移除,最好是在其余地方定义事件处理程序的函数,而后将该函数的名称传给第二个参数。
var btn = document.getElementById("myBtn"); //定义事件处理程序函数 var handler = function(){ alert(this.id); } btn.addEventListener("click", handler, false); btn.removeEventListener("click", handler, false);
支持IE事件处理程序的浏览器有IE和Opera
IE定义了两个与DOM2级相似的方法:
var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function(){ alert(this.id); });
注:
为了保证跨浏览器的兼容性,咱们定义一个EventUtil对象,它包含addHandler()和removeHandler()两个方法。
var EventUtil = { //addHandler()方法 addHandler:function(element, type, handler){ //DOM2级事件处理程序 if(element.addEventListener){ element.addEventListener(type, handler, false); } //IE事件处理程序 else if(element.attachEvent){ element.attachEvent("on"+type, handler); } //默认使用DOM0级事件处理程序 else{ element["on"+type]=handler; } }, //removeHandler()方法 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]=handler; } } };
触发DOM上的某个事件时,会产生一个event事件对象,该对象包含着全部与事件有关的信息。
全部浏览器都支持event对象,但支持的方式不一样。
兼容DOM(DOM0级和DOM2级)的浏览器将event对象传入到事件处理程序中。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.type); //"click" }; btn.addEventListener("click", function(event){ alert(event.type); //"click" }, false);
event对象的属性和方法以下图所示:
在上图中,currentTarget的值始终等于this,而target只包含事件的实际目标。
若是直接将事件处理程序指定给了目标元素,则this === currentTarget === target
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.currentTarget === this); //true alert(event.target === this); //true } //上例中,点击事件的目标是按钮,而且把事件处理程序直接给了目标元素,因此三者的值相等
若是将事件处理程序没有直接指定给目标元素,this === currentTarget !== target
document.body.onclick = function(event){ alert(event.currentTarget === document.body); //true alert(this === document.body); //true alert(target === document.getElementById("myBtn")); //true } //上例中,点击世界的目标是按钮,可是事件处理程序制定给了body元素,故三者并不相等。
在IE中,指定事件处理程序的方法不一样,访问event对象的方法也不一样:
(1)使用DOM0级添加事件处理程序 —— event对象是window对象的一个属性
var btn = document.getElementById("myBtn"); btn.onclick = function(){ var event = window.event; alert(event.type); //"click" }
(2)使用attachEvent()添加事件处理程序 —— event对象会被传入事件处理程序函数中
var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function(event){ alert(event.type); //"click" });
(3)经过HTML特性指定事件处理程序 —— 经过event变量来访问event对象
<input type="button" vaule="Click me" onclick="alert(event.type)"/>
虽然DOM和IE中的event对象不一样,但基于它们之间的类似性,能够实现跨浏览器的兼容性
var EventUntil = { //省略代码 addHandler: function(element, type, handler){}, //获取event对象 getEvent: function(event){ return event ? event : window.event; }, //获取target getTarget: function(event){ return event.target||event.srcElement; }, //取消事件的默认行为 preventDefault: function(event){ if(event.preventDefault){ event.preventDefault(); } else{ event.returnValue = false; } }, //取消冒泡 stopPropagation: function(event){ if(event.stopPropagation){ event.stopPropagation(); } else{ event.cancelBubble = true; } }, //省略代码 removeHandler:function(element, type, handler){} };