对“捕获”和“冒泡”这两个概念,通常我们对冒泡了解和使用的会更多一些,因为在我们使用的所有浏览器中,都支持事件冒泡 ,即事件由子元素向祖先元素传播的,就 像气泡从水底向水面上浮一样。而在像firefox,chrome,safari这类所谓的标准浏览器中,事件传播通常是有三个阶段的:事件捕获阶段,事件目标阶段,事件冒泡阶段,这三者的执行的顺序是先捕获在冒泡。对于捕获阶段,这个很少 有用武之地,所以被人疏忽遗忘也在所难免了,不常用不代表它不存在,本着科学严谨的态度,我们有必要去看一下它的庐山真面目。
事件冒泡:事件冒泡指的是当前的目标元素触发事件的发生,事件在一次向祖先元素传播,在祖先元素上触发相同类型的事件。当子元素都有同一事件处理程序时,利用事件的冒泡可以减少代码的冗余度。通过给元素对象绑定事件的方法addEventlistener()第三个参数决定事件的执行阶段是在冒泡阶段还是捕获阶段,当第三个参数为true时,为冒泡阶段,通常省略该参数是默认的是冒泡,如果为false则是捕获阶段。为了兼容IE8以及IE8之前版本浏览器可以通过attachEvent()方法给元素添加事件不过他没有第三个参数。下面的例子是没有阻止事件冒泡时的代码,最终会看到,当点击了ele2时,事件会向上冒泡依次输出ele2,ele,ele0,这个就是由于事件的冒泡引起的。
1 <html> 2 <head> 3 <meta charset="utf-8"> 4 <title>bubble event</title> 5 <style> 6 .ele0{ 7 width:400px; 8 height:400px; 9 border:1px solid black; 10 background-color:red; 11 position:relative; 12 } 13 .ele1{ 14 width:300px; 15 height:300px; 16 border:1px ; 17 background-color:green; 18 position:absolute; 19 top:0; 20 } 21 .ele2{ 22 width:200px; 23 height:200px; 24 border:1px ; 25 background-color:blue; 26 position:absolute; 27 top:0; 28 } 29 </style> 30 <script> 31 window.onload=function(){ 32 var ele=document.getElementsByTagName("div"); 33 34 if(ele[0].addEventListener) 35 { 36 ele[0].addEventListener("click", function (){ 37 38 console.log("点击的是盒子ele0!"); 39 }); 40 } 41 42 else{ 43 ele[0].attachEvent("onclick",function (){ 44 console.log("点击的是盒子ele0!"); 45 46 }); 47 } 48 if(ele[1].addEventListener) 49 { 50 ele[1].addEventListener("click", function (){ 51 52 console.log("点击的是盒子ele1!"); 53 }); 54 } 55 56 else{ 57 ele[1].attachEvent("onclick",function (){ 58 console.log("点击的是盒子ele1!"); 59 60 }); 61 } 62 63 if(ele[2].addEventListener) 64 { 65 ele[2].addEventListener("click", function (){ 66 67 console.log("点击的是盒子ele2!"); 68 }); 69 } 70 71 else{ 72 ele[2].attachEvent("onclick",function (){ 73 console.log("点击的是盒子ele2!"); 74 75 }); 76 } 77 78 } 79 </script> 80 </head> 81 <body> 82 <div class="ele0"> 83 <div class="ele1"><div class="ele2"></div></div> 84 85 </div> 86 </body> 87 <html>
事件捕获:事件捕获过程与事件的冒泡阶段是一个相反的阶段,即事件由祖先元素向子元素传播,和一个石子儿从水面向水底下沉一样,要说明的是在 IE,opera浏览器中,是不存在这个阶段的。在上述的代码中给事件监听程序添加第三个参数false,当点击元素ele2时会看到不一样的效果,输出结果中将会最先输出ele0,而不是ele2,这就是事件的捕获。
阻止事件的冒泡:
有时候事件的冒泡回会导致程序的运行顺序和自己想象的情形不一样,这时候就需要对事件的冒泡进行阻止。阻止事件的冒泡的方法与事件处理程序的添加方式有关:
1.如果事件是在HTML中通过属性或者是元素对象的属性添加的即 onclick="function(){}"或者ele.onclick=function(){}方式。要阻止事件的冒泡只需要在处理程序的最后加上return false;即可。
2.在IE8以上的版本以及其他的浏览器中通过e.stopPropagation()方式阻止事件的冒泡。在 支持该方法的浏览器中还有一个方法stopimmediatePropagation(),该方法不仅会组织事件向祖元素的冒泡,同时也会阻止同一个节点上同一事件的其他的事件处理程序的执行,该方法比前者阻止的更彻底。
3.在IE8以及IE以下的浏览器中通过e.cancleBubble=true,阻止事件冒泡。
1 <html> 2 <head> 3 <meta charset="utf-8"> 4 <title>bubble event</title> 5 <style> 6 .ele0{ 7 width:400px; 8 height:400px; 9 border:1px solid black; 10 background-color:red; 11 position:relative; 12 } 13 .ele1{ 14 width:300px; 15 height:300px; 16 border:1px ; 17 background-color:green; 18 position:absolute; 19 top:0; 20 } 21 .ele2{ 22 width:200px; 23 height:200px; 24 border:1px ; 25 background-color:blue; 26 position:absolute; 27 top:0; 28 } 29 </style> 30 <script> 31 window.onload=function(){ 32 var ele=document.getElementsByTagName("div"); 33 34 if(ele[0].addEventListener) 35 { 36 ele[0].addEventListener("click", function (e){ 37 38 console.log("点击的是盒子ele0!"); 39 e.stopPropagation(); 40 }); 41 42 } 43 44 else{ 45 ele[0].attachEvent("onclick",function (e){ 46 console.log("点击的是盒子ele0!"); 47 e=window.event; 48 e.cancleBubble=true; 49 50 }); 51 } 52 if(ele[1].addEventListener) 53 { 54 ele[1].addEventListener("click", function (e){ 55 56 console.log("点击的是盒子ele1!"); 57 e.stopPropagation(); 58 }); 59 } 60 61 else{ 62 ele[1].attachEvent("onclick",function (e){ 63 console.log("点击的是盒子ele1!"); 64 e=window.event; 65 e.cancleBubble=true; 66 67 }); 68 } 69 70 if(ele[2].addEventListener) 71 { 72 ele[2].addEventListener("click", function (e){ 73 74 console.log("点击的是盒子ele2!"); 75 e.stopPropagation(); 76 }); 77 } 78 79 else{ 80 ele[2].attachEvent("onclick",function (e){ 81 console.log("点击的是盒子ele2!"); 82 e=window.event; 83 e.cancleBubble=true; 84 85 }); 86 } 87 88 } 89 </script> 90 </head> 91 <body> 92 <div class="ele0"> 93 <div class="ele1"><div class="ele2"></div></div> 94 95 </div> 96 </body> 97 <html>