关于事件捕获和事件冒泡
这篇随笔主要是写关于事件冒泡和事件捕获的一些关联,主要是从《JavaScript高级程序设计》这本书第13章总结扩展而来,今天主要是想扩展对书本里面P358页以及加深一下理解。
一、先说一下定义:
事件冒泡阶段:从最具体的元素,即目标事件位置往文档的根节点方向回溯,从内向外冒泡事件对象(所有浏览器都支持)。
事件捕获阶段:先由文档的根节点document往事件触发对象,从外向内捕获事件对象(DOM2级事件要求事件从document对象开始传播,但是IE9,Safari,Chrome,Opera,Firefox都是从window对象开始捕获事件的,老版本的浏览器不支持事件捕获)。
目标阶段:到达被触发的元素。
事件处理程序是否指定给目标元素怎么看?如果触发的函数直接绑定在目标元素上面的话,那么事件处理程序就是直接指定给目标元素。在事件处理程序内部,对象 this 始终等于 currentTarget 的值,而 target 则只包含事件的实 际目标。如下面的代码:
(1)事件处理程序就是直接指定给目标元素
<input type="button" value="点击" id="btn">
var btn = document.getElementById("btn");
btn.onclick = function(){ //红色部分就是事件处理程序,假设我们此时点击按钮,那么此时事件处理程序直接指定给目标元素id为btn的按钮
console.log(event.currentTarget === this); //true,此时this,currentTarget,target的值都相同
console.log(event.target === this); //true
}
(2)事件处理程序就是未直接指定给目标元素
<input type="button" value="点击" id="btn">
var btn = document.getElementById("btn");
document.body.onclick = function(){ //假设我们此时点击按钮,那么此时事件处理程序是指定给body
console.log(event.currentTarget === document.body); //true,此时this,currentTarget的值都相同
console.log(this === document.body); //true
console.log(event.target === document.getElementById("btn")); //true
}
二、"DOM2级事件"规定事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。首先是事件捕获(此时可以截获事件);然后就是实际的目标接收到事件;最后就是冒泡阶段,可以再这个阶段对事件作出响应。
(此图片来源百度图片)
接下来就是扩展的问题啦啦啦啦,集中精神。
1.先单独看一下冒泡和捕获的过程
(1)冒泡过程:
代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 *{ 7 font-size: 20px; 8 color: white; 9 } 10 #one{ 11 width: 400px; 12 height: 400px; 13 background-color: pink; 14 } 15 #two{ 16 width: 300px; 17 height: 300px; 18 background-color: green; 19 } 20 #three{ 21 width: 200px; 22 height: 200px; 23 background-color: blue; 24 } 25 #four{ 26 width: 100px; 27 height: 100px; 28 background-color: black; 29 } 30 </style> 31 <script type="text/javascript"> 32 window.onload = function(){ 33 var one=document.getElementById('one'); 34 var two=document.getElementById('two'); 35 var three=document.getElementById('three'); 36 var four=document.getElementById('four'); 37 one.addEventListener('click',function(){ 38 console.log('one冒泡'); 39 },false); 40 two.addEventListener('click',function(){ 41 console.log('two冒泡'); 42 },false); 43 three.addEventListener('click',function(){ 44 console.log('three冒泡'); 45 },false); 46 four.addEventListener('click',function(){ 47 console.log('four冒泡'); 48 },false); 49 } 50 </script> 51 </head> 52 <body> 53 <div id='one'> 54 one 55 <div id='two'> 56 two 57 <div id='three'> 58 three 59 <div id='four'> 60 four 61 </div> 62 </div> 63 </div> 64 </div> 65 </body> 66 </html>
效果图:
(2)捕获过程:
代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 *{ 7 font-size: 20px; 8 color: white; 9 } 10 #one{ 11 width: 400px; 12 height: 400px; 13 background-color: pink; 14 } 15 #two{ 16 width: 300px; 17 height: 300px; 18 background-color: green; 19 } 20 #three{ 21 width: 200px; 22 height: 200px; 23 background-color: blue; 24 } 25 #four{ 26 width: 100px; 27 height: 100px; 28 background-color: black; 29 } 30 </style> 31 <script type="text/javascript"> 32 window.onload = function(){ 33 var one=document.getElementById('one'); 34 var two=document.getElementById('two'); 35 var three=document.getElementById('three'); 36 var four=document.getElementById('four'); 37 one.addEventListener('click',function(){ 38 console.log('one捕获'); 39 },true); 40 two.addEventListener('click',function(){ 41 console.log('two捕获'); 42 },true); 43 three.addEventListener('click',function(){ 44 console.log('three捕获'); 45 },true); 46 four.addEventListener('click',function(){ 47 console.log('four捕获'); 48 },true); 49 } 50 </script> 51 </head> 52 <body> 53 <div id='one'> 54 one 55 <div id='two'> 56 two 57 <div id='three'> 58 three 59 <div id='four'> 60 four 61 </div> 62 </div> 63 </div> 64 </div> 65 </body> 66 </html>
效果图:
2.既有捕获又有冒泡时的过程:
代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 *{ 7 font-size: 20px; 8 color: white; 9 } 10 #one{ 11 width: 400px; 12 height: 400px; 13 background-color: pink; 14 } 15 #two{ 16 width: 300px; 17 height: 300px; 18 background-color: green; 19 } 20 #three{ 21 width: 200px; 22 height: 200px; 23 background-color: blue; 24 } 25 #four{ 26 width: 100px; 27 height: 100px; 28 background-color: black; 29 } 30 </style> 31 <script type="text/javascript"> 32 window.onload = function(){ 33 var one=document.getElementById('one'); 34 var two=document.getElementById('two'); 35 var three=document.getElementById('three'); 36 var four=document.getElementById('four'); 37 one.addEventListener('click',function(){ 38 console.log('one捕获'); 39 },true); 40 two.addEventListener('click',function(){ 41 console.log('two冒泡'); 42 },false); 43 three.addEventListener('click',function(){ 44 console.log('three捕获'); 45 },true); 46 four.addEventListener('click',function(){ 47 console.log('four冒泡'); 48 },false); 49 } 50 </script> 51 </head> 52 <body> 53 <div id='one'> 54 one 55 <div id='two'> 56 two 57 <div id='three'> 58 three 59 <div id='four'> 60 four 61 </div> 62 </div> 63 </div> 64 </div> 65 </body> 66 </html>
效果图:
3.如果一个元素同时绑定了两个事件,既有冒泡事件,又有捕获事件时,应该执行几次,先后顺序是什么?
(1)绑定多少个事件就执行多少次事件。
(2)执行顺序问题:
【1】如果多次绑定事件的元素是目标元素,那么执行时就按照绑定的顺序执行(注意:这里说的按照绑定顺序执行是指利用addEventListener来绑定事件的;如果是利用attachEvent来绑定事件的,就是以绑定时的相反顺序执行),其他元素就按照先捕获后冒泡的顺序执行。
代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 *{ 7 font-size: 20px; 8 color: white; 9 } 10 #one{ 11 width: 400px; 12 height: 400px; 13 background-color: pink; 14 } 15 #two{ 16 width: 300px; 17 height: 300px; 18 background-color: green; 19 } 20 #three{ 21 width: 200px; 22 height: 200px; 23 background-color: blue; 24 } 25 #four{ 26 width: 100px; 27 height: 100px; 28 background-color: black; 29 } 30 </style> 31 <script type="text/javascript"> 32 window.onload = function(){ 33 var one=document.getElementById('one'); 34 var two=document.getElementById('two'); 35 var three=document.getElementById('three'); 36 var four=document.getElementById('four'); 37 one.addEventListener('click',function(){ 38 console.log('one捕获'); 39 },true); 40 two.addEventListener('click',function(){ 41 console.log('two冒泡'); 42 },false); 43 three.addEventListener('click',function(){ 44 console.log('three冒泡'); 45 },false); 46 three.addEventListener('click',function(){ 47 console.log('three捕获'); 48 },true); 49 four.addEventListener('click',function(){ 50 console.log('four冒泡'); 51 },false); 52 } 53 </script> 54 </head> 55 <body> 56 <div id='one'> 57 one 58 <div id='two'> 59 two 60 <div id='three'> 61 three 62 <div id='four'> 63 four 64 </div> 65 </div> 66 </div> 67 </div> 68 </body> 69 </html>
【2】如果多次绑定事件的元素没有被触发,而是触发其他元素,那么多次绑定的元素的事件的执行顺序就是按照"DOM2级事件"规定的那样,先捕获,后目标元素,最后冒泡。
代码同【1】中代码一样,只是这次是触发id为four这个div,效果图如下:
OK,大概的扩展和进一步的理解就到这里,加油,在变得越来越优秀的路上,哈哈。