1.事件冒泡:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
IE 5.5: div -> body -> document
IE 6.0: div -> body -> html -> document
Mozilla 1.0: div -> body -> html -> document -> window
2.事件捕获:事件从最不精确的对象(document 对象)开始触发,然后到最精确target
3.DOM事件流:同时支持事件捕获与事件冒泡,事件捕获发生在事件冒泡之前,DOM事件模型最独特的性质是,文本节点也触发事件(在IE中不会)。
下图是DOM事件流中的事件捕获与事件冒泡过程:
js中事件监听方法总共有三种,分别如下所示:
- element.addEventListener(type, listener[, useCapture]); // IE6~8不支持
- element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持
- element[’on’ + type] = function(){} // 所有浏览器
支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行。
传统的element[’on’ + type] = function(){}与addEventListener(event,fn,useCapture)区别在于element[’on’ + type] = function(){}无法进行事件捕获,并且element[’on’ + type] = function(){}不支持对同一个元素的同一个事件注册多个事件监听器,后定义的事件会覆盖先定义的事件。
4.事件捕获的小实验,代码如下:
实验一:
1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <style type="text/css"> 7 body{ 8 background-color: yellow; 9 } 10 11 div{ 12 background-color: red; 13 padding: 100px; 14 } 15 img{ 16 padding: 50px; 17 } 18 19 </style> 20 </head> 21 <body id="body"> 22 <div id="div"> 23 <img src="frame.gif" id="img" /> 24 </div> 25 <script type="text/javascript"> 26 function onBody(event){ 27 console.log("event capture in body"); 28 29 } 30 function onDiv(event){ 31 console.log("event capture in div"); 32 event.bubbles=true; 33 } 34 function onImg(event){ 35 console.log("event capture in img"); 36 event.bubbles=true; 37 } 38 window.onload=function(){ 39 var aimg=document.getElementById("img"); 40 aimg.addEventListener("click",onImg); 41 var adiv=document.getElementById("div"); 42 adiv.addEventListener("click",onDiv); 43 var abody=document.getElementById("body"); 44 abody.addEventListener("click",onBody,true); 45 } 46 </script> 47 </body> 48 </html>
这是一个简单的小实验,其中定义了三个function,分别为onDiv,onImg,onBody,其中onBody的第三个参数定义为true,说明该函数在事件捕获时执行。
在Chrome浏览器下,单击img部分得到的结果如下:
由于单击事件最直接的target是img,onbody添加了事件捕获时执行的函数,所以会输出第一行,第二行是事件直接触发img上的事件,输出第二行,第三行是事件冒泡时执行了定义在div上的函数,输出第三行。
实验二:
如果将onBody的addEventListener的第三个参数不添加或者改成false,那么onBody的函数就会在事件冒泡时执行,得到如下结果: