事件就是用户或者浏览器自身执行的某种动做。诸如click、load和mouseover,都是事件的名字。而响应某个事件的函数就叫事件处理程序。事件处理程序的名字以“on”开头,好比click事件的事件处理程序是onclick。为事件指定事件处理程序的方式有多种方式。浏览器
元素支持的事件,均可以使用与相应事件处理程序同名的HTML特性来指定。这个特性的值能支持必定的JavaScript代码。例如,在单击按钮的时候执行一些JavaScript代码。 <div id="aa" onclick="console.log('div')" style="width: 100px;">2222</div> ,当单击这个div的时候,会在浏览器的控制台中输出div。这个特性是经过JavaScript来实现的,不能在其中使用未经转义的HTML语法字符,例如和号(&)、双引号("")、单引号('')、小于号(<)或者大于号(>)。函数
在HTML中定义的事件处理程序能够包含要执行的具体动做,也能够调用定义在其余页面的脚本。this
1 function divClick(e){ 2 var target=e.target; 3 console.log("div"); 4 //stopBubble(e); 5 }
<div id="aa" onclick="divClick(event);" style="width: 100px;">2222</div> spa
上面的代码中,点击div以后就会调用divClick函数。这个函数是单独定义的script脚本中的,固然也能够定义在一个外部文件中。事件处理程序中的代码,能够访问全局的方法。上面的代码中,一样能够传递event参数以及this参数。event参数可以获取事件的类型参数等,经过this可以获取点击对象自己。code
1 function divClick(e){ 2 //var target=e.target; 3 console.log($(e).text());//222 4 //stopBubble(e); 5 }
<div id="aa" onclick="divClick(this);" style="width: 100px;">2222</div> 对象
在HTML中指定事件处理程序有必定的缺点:存在必定的时差,用户可能在页面一出现就触发相应的事件,可是事件处理程序尚不具有执行的条件。上面的例子上,若是divClick函数定义在div的下方,咱们在函数还没有解析以前,就点击div,这样就会致使报错。blog
另外一个缺点是,这样的事件处理程序的做用域链在不一样的浏览器中会致使不一样结果。不一样JavaScript引擎遵循的标识符解析规则略有差别,极可能在访问非限定对象时出错。seo
经过HTML指定事件处理程序的最后一个缺点是HTML与JavaScript代码的紧密耦合。若是要更换事件处理程序就须要改动两个地方:JavaScript和HTML。事件
经过JavaScript指定事件处理程序的传统方式是将一个函数赋值给事件处理程序属性。经过JavaScript指定事件处理程序有两个优点:简单和浏览器兼容性好。要使用JavaScript指定事件处理程序,首先必须获取一个元素的对象引用。每一个元素都有本身的事件处理程序,这个属性一般是所有小写,好比onclick。ip
1 <div id="aa" style="width: 100px;">2222</div> 2 <script> 3 var a=document.getElementById("aa"); 4 a.onclick=function(e){ 5 var target=e.target; 6 var text=target.innerHTML; 7 console.log(text);//222 8 } 9 </script>
上面的代码,经过文档对象获取了对象的引用,而后为它指定了onclick事件处理程序。e为点击事件的参数,经过该参数可以获取点击事件的对象,即target。经过对象能够进一步获取对象的属性。
1 <div id="aa" style="width: 100px;">2222</div> 2 <script> 3 $("#aa").click(function(e){ 4 var target=e.target; 5 var text=target.innerHTML; 6 console.log(text);//222 7 }); 8 </script>
这段代码与上面的例子实现的是同样的效果,可是这个是经过JQuery来实现的。
DOM2级事件处理程序定义了两个方法,用于处理指定和删除事件处理程序的操做:addEventListener和removeEventListener。全部DOM节点都包含这两个方法,而且他们接收3个参数:要处理的事件名、做为事件处理程序的函数和一个布尔值。布尔值若是为true,表示在捕获阶段执行事件处理程序,若是为false,表示在冒泡阶段调用事件处理程序。
1 <div id="aa" style="width: 100px;">2222</div> 2 <script> 3 var a=document.getElementById("aa"); 4 a.addEventListener("click",function(e){ 5 console.log(this.id); 6 },false); 7 </script>
上面的例子经过addEventListener为元素aa添加了一个click事件。经过事件处理程序可以访问到元素,this和元素处在同一个做用域链。
经过DOM2级能够经过添加多个事件处理程序。事件处理程序会按照添加的顺序依次触发。
1 var a=document.getElementById("aa"); 2 a.addEventListener("click",function(e){ 3 console.log(this.id); 4 },false); 5 a.addEventListener("click",function(e){ 6 console.log(this.innerHTML); 7 },false);
经过addEventListener添加的事件处理程序,能够经过removeEventListener来移除事件处理程序。可是,有时候咱们会走入一个误区。
1 var a=document.getElementById("aa"); 2 a.addEventListener("click",function(e){ 3 console.log(this.id); 4 },false); 5 a.removeEventListener("click",function(e){ 6 console.log(this.id); 7 },false);
上面的代码咱们使用removeEventListener方法移除事件处理程序,可是并无起做用。在使用addEventListener和removeEventListener的时候,第二个事件处理程序函数必须是同一个函数才会有做用,咱们对上面的代码做一个修改,就能够了。
1 var a=document.getElementById("aa"); 2 var callback=function(e){ 3 console.log(this.id); 4 } 5 a.addEventListener("click",callback,false); 6 a.removeEventListener("click",callback,false);
上面的代码中,咱们在addEventListener和removeEventListener中调用的是同一个方法,因此元素aa已经没有点击事件。
对于IE8以及IE8如下浏览器来讲,它们并无上述的两个方法,可是提供了attachEvent和detachEvent两个方法。这两个只须要传递两个参数:第一参数事件程序名称,第二个事件处理程序函数。
1 var a=document.getElementById("aa"); 2 var callback=function(e){ 3 console.log(e.target.innerHTML); 4 } 5 //a.addEventListener("click",callback,false); 6 //a.removeEventListener("click",callback,false); 7 a.attachEvent("onclick",callback);
上面的代码经过attachEvent添加了事件处理程序,可是attachEvent与addEventListener不同。在attachEvent的事件处理程序函数中this是指向window的,咱们没法获取元素对象。
1 var a=document.getElementById("aa"); 2 var callback=function(e){ 3 console.log(this.id); 4 } 5 //a.addEventListener("click",callback,false); 6 //a.removeEventListener("click",callback,false); 7 a.attachEvent("onclick",function(e){ 8 callback.call(a,e); 9 });
上面的代码,咱们经过call修改了this的指向,可是这样会带来另一个问题,怎么detachEvent?
为了以跨浏览器的事件处理程序,开发人员能够封装适合本身的js库。
1 var EventUtil={ 2 addEvent:function(element,type,fn){ 3 if(element.addEventListener){ 4 element.addEventListener(type,fn,false); 5 } 6 else if(element.attachEvent){ 7 element.attachEvent("on"+type,fn); 8 } 9 else{ 10 element["on"+type]=fn; 11 } 12 }, 13 removeEvent:function(element,type,fn){ 14 if(element.removeEventListener){ 15 element.removeEventListener(type,fn,false); 16 } 17 else if(element.detachEvent){ 18 element.detachEvent("on"+type,fn); 19 } 20 else{ 21 element["on"+type]=null; 22 } 23 } 24 }; 25 var aa=document.getElementById("aa"); 26 var func=function(e){ 27 console.log(e.type); 28 EventUtil.removeEvent(aa,"click",func); 29 } 30 EventUtil.addEvent(aa,"click",func);
上面的EventUtil封装了一个跨浏览器的对象,包含两个方法addEvent和removeEvent。在第25行获取元素对象引用,26行定义了fn函数,30行调用addEvent添加了事件处理程序。这个事件处理程序只能执行一次,由于咱们在func函数中又调用了removeEvent函数。