事件
事件:就是文档或浏览器窗口中发生的一些特定的交互瞬间。
事件流:描述的是从页面中接收事件的顺序。
事件流分为两种:冒泡流、捕获流
事件冒泡:
IE的事件流叫做事件冒泡 (event bubbling), 既时间开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的 1 <!DOCTYPE html>
2 <html> 3 <head> 4 </head> 5 <body> 6 <div id="outer">
Click Me
11 </div> 12 </body> 13 </html>
如果单击了 div时,按照事件冒泡规则:
1 div 2 body 3 html 4 document
当点击div时,click事件会沿着dom树向上传播,逐层执行,直到document
在现代浏览器中基本上支持事件冒泡,只是细微的差别,IE5以及更早版本中,事件冒泡的顺序会有所不同(body-document) ; 在IE safari Firefox Chrome 将事件冒泡到了window对象。
事件捕获:
不太具体的元素应该先最早收到事件,具体元素应该最后收到事件。 事件捕获的用意在于时间到达预定目标之前捕获它。同上例子作为参考的话,那么点击div元素就会一下顺序触发click 事件
1 document 2 html 3 body 4 div
当点击div时候,document最新获得具体的事件,再沿着dom结构往下传递,最后到目标对象。
DOM事件流
“DOM2级事件” 规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。 首先发生的是事件捕获,为截获事件提供了机会。然后就是实际的目标接收事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件作出响应。
在dom事件流中,阶段目标在捕获阶段是获取不到的事件的,那相当于捕获阶段为(Document html body),而下一个阶段从目标对象开始逐层向上传递。
事件处理程序:
事件就是用户或浏览器自身执行某种动作。 诸如click 、load 和 mouseover, 都是事件的名字。而响应某个事件的函数就叫做事件处理程序(或事件侦听器). 事件处理程序的名字以on开头。
为事件指定处理程序的方式有好几种。
1> HTML事件处理程序
某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来制定(也就是HTML属性)。
1 <input type="button" value="Click Me" onclick="alert('Clicked')">
2> DOM0级事件处理程序
通过JavaScript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。
1 var btn = document.getElementById("myBtn"); 2 btn.onclick = function(){ 3 alert(this.id); // myBtn 4 }
已这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。
也可以删除通过DOM0级方法指定的事件处理程序,只要像下面这样将事件处理程序属性的值设置为 null 即可
btn.onclick = null
3> DMO2级事件处理程序
Dom2级事件 定义了两个方法,用于处理指定和删除事件处理程序的操作: addEventListener()和 removeEventListtener(). 所有dom节点中都包含着两个方法
两个方法接受三个参数:
@param1 要处理的事件名
@param2 作为事件处理程序的函数
@param3 布尔值 如果true 表示在捕获阶段调用事件处理程序; 如果是false 表示在冒泡阶段调用事件处理程序。
要在按钮上为 click 事件添加处理程序,代码如下
1 var btn = document.getElementById("myBtn"); 2 btn.addEventListener("click",function(){ 3 alert(this.id); 4 },false)
处理程序也是在其负数的元素的作用域中运行。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。来看下面的
var btn = document.getElementById("myBtn"); btn.addEventListener("click",function(){ alert(this.id); },false) btn.addEventListener("click",function(){ alert("Hello word"); },false)
事件执行顺序按照它们的添加顺序触发,因此首先会显示元素的ID,其次会显示"Hello world"
注意: 通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;传递的参数与添加事件处理程序时的参数列表一样。这也意味着addEventListener()添加的匿名函数不能移除;
1 var btn = document.getElementById("myBtn"); 2 btn.addEventListener("click",function(){ 3 alert(this.id); 4 },false); 5 6 btn.removeEventListener("click",function(){ alert(this.id);},false); //无效
不过可以通过如下这种方式:
var btn = document.getElementById("myBtn"); var handler = function(){ alert(this.id); }; btn.addEventListener("click",handler,false); btn.removeEventListener("click",handler,false);
大多数情况下,都是在添加在事件冒泡阶段,这样更大程度的兼容大多数浏览器。最好只有在事件到达目标之前截获它的时候将事件处理程序添加到捕获阶段。
IE9 、Firefox、Safari、Chrome 和 Opera 支持DOM2级事件处理程序。
IE事件处理程序
为了兼容IE8以及更早版本,IE通过 attachEvent()和 detachEvent() 这两个方法接受相同的两个参数:事件处理程序名称与事件处理函数。由于IE8及更早的版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡泡阶段。
要使用attachEvent()为按钮添加一个事件处理程序,可以使用以下代码。
1 var btn = document.getElementById("myBtn"); 2 var handler = function(){ 3 alert("ggggggggg"); 4 }; 5 btn.attachEvent("onclick",handler);
注意: attrachEvent 的第一个参数是“onclick”,而非DOM的addEventListener()方法中的“click”
在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。在使用DOM0级方法的情况下,事件处理程序会在其所属的元素作用域内运行;
在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window。来看下面的例子
1 var btn = document.getElementById("myBtn"); 2 var handler = function(){ 3 alert(this==window); //true 4 }; 5 btn.attachEvent("onclick",handler);
与 addEventListener()类似,attachEvent()方法也可以用来为一个元素添加多个事件处理程序。来看下面的例子
var btn = document.getElementById("myBtn"); var handler = function(){ alert(this==window); //true }; btn.attachEvent("onclick",handler); btn.attachEvent("onclick",function(){ alert("第二个"); });
在IE8以及更低版本中,attachEvent 事件的执行顺序与 addEventListener想反,不按照追加顺序执行,而是相反的顺序;结果如下
1 第二个 2 true
使用attachEvent()添加的事件可以通过 detachEvent()来移除,条件是必须提供相同的参数。与DOM方法一样,也意味者匿名函数不能够删除。
1 var btn = document.getElementById("myBtn"); 2 var handler = function(){ 3 alert(this==window); //true 4 }; 5 btn.attachEvent("onclick",handler); 6 btn.detachEvent("onclick",handler);
支持IE事件处理程序的浏览器:IE和Opera
通过上面三种事件处理程序我们可以写一个跨浏览器的事件处理程序;
1 var EventUtil = { 2 addHandler:function(element,type,handler){ 3 if(element.addEventListener){ 4 element.addEventListener(type,handler,false); 5 }else if(element.attachEvent){ 6 element.attachEvent("on"+type,handler); 7 }else{ 8 element["on"+type] = handler; 9 } 10 }, 11 removeHandler:function(){ 12 if(element.removeEventListener){ 13 element.removeEventListener(type,handler,false); 14 }else if(element.detachEvent){ 15 element.detachEvent("on"+type,handler); 16 }else{ 17 element["on"+type] = null; 18 } 19 } 20 21 }