在類似於arcgis api for javascript中,經常會遇到function(e),以前一直不懂e是個什么玩意,這種寫法啥意思,經過最近一段時間學習,對e有了很深了解,本文通過各種示例,由事件階段----事件委托----事件對象逐個總結,最后對e的各種屬性,應用加以實踐。
*********************************************************************************************************************************************************************
*********************************************************************************************************************************************************************
一、事件的三個階段
事件觸發時候會經歷三個階段:①事件捕獲階段 ②執行階段(執行當前元素的注冊事件) ③事件冒泡階段。本節通過一個示例,對三個階段加以總結
引入:addEventListener(type,listener,userCapture)
type:事件名稱 click mouseover mouseout
listener:事件注冊函數
userCapture:可選,bool類型,默認為false
示例:
示例描述:頁面中嵌套三個盒子,box1,box2,box3(從外到內,依次是紅色,綠色,藍色),給三個盒子都注冊點擊事件,輸出三個盒子的id,點擊藍色盒子,結果如下:
頁面效果: 點擊藍色盒子,控制台輸出結果: 點擊紅色盒子,控制台輸出結果:
分析:
在上述代碼中,給addEventListener的userCapture屬性賦值為true,此時事件階段是事件捕獲階段。
當addEventListener的userCapture屬性賦值為false時,此時事件階段是事件冒泡階段。
當屬性為false時候,從里往外執行,這種執行效果稱為事件冒泡,就像一個氣泡從水里最深處往外冒一樣。事件冒泡從里面往外面泡,從最小的元素一直往外傳遞,傳遞到最外層的元素。此時,在事件執行過程中,先執行事件捕獲,box1-->box2-->box3,執行完box3的點擊事件后,再從里向外執行,box3-->box2-->box1.
在代碼中,只能處理事件捕獲或者事件冒泡其中的一個階段,其實這三個階段都會發生,當點擊box3時候,事件捕獲也發生了,只不過沒辦法通過代碼進行干預。
當在上述代碼中,給addEventListener的userCapture屬性賦值為true,選執行最外層的box1,再執行box2,box3,這種從外向里的過程是事件捕獲。
onclik/attachEvent都不能設置冒泡或者捕獲階段,他們都是事件冒泡,我們最需要重視的也是事件冒泡
代碼如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>事件冒泡</title> 6 <style type="text/css"> 7 #box1{ 8 width: 300px; 9 height: 300px; 10 background-color: red; 11 } 12 #box2{ 13 width: 200px; 14 height: 200px; 15 background-color: green; 16 } 17 #box3{ 18 width: 100px; 19 height: 100px; 20 background-color: blue; 21 } 22 </style> 23 </head> 24 <body> 25 <div id="box1"> 26 <div id="box2"> 27 <div id="box3"></div> 28 </div> 29 </div> 30 <!-- 插入JS代碼 --> 31 <script type="text/javascript"> 32 //獲取所有的box 33 var box1=document.getElementById('box1'); 34 var box2=document.getElementById('box2'); 35 var box3=document.getElementById('box3'); 36 //給三個box注冊點擊事件 建議使用數組 37 var boxs=[box1,box2,box3]; 38 for(var i=0;i<boxs.length;i++){ 39 boxs[i].addEventListener('click',outPut,true); 40 } 41 //點擊事件函數 42 function outPut(){ 43 console.log(this.id); 44 } 45 </script> 46 </body> 47 </html>
**********************************************************************************************************************************************************************************
**********************************************************************************************************************************************************************************
二、事件冒泡的作用------事件委托
事件冒泡的作用通過事件委托來體現,也是通過一個示例,來了解事件委托。
需求:點擊頁面中各個項,點擊哪個項,哪個項背景高亮顯示。
頁面效果如下:
在網頁中,有一個ul標簽,ul中包括6個標簽,要實現上面效果,以前的做法是首先找到ul,然后找到ul里面所有的li,遍歷所有的li標簽,給它們逐個注冊點擊事件。
現在,有了事件冒泡,就不用給每一個li注冊點擊事件了。因為冒泡事件的作用,點擊li元素的時候,點擊事件可以傳送到父元素上來,即本來該li做的事情,交給ul去做,再者就是事件委托。
代碼如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>事件冒泡的作用----事件委托</title> 6 <!-- 點擊li標簽內容,讓其背景高亮顯示 --> 7 </head> 8 <body> 9 <ul id="ul"> 10 <li>夏侯惇</li> 11 <li>夏侯淵</li> 12 <li>典韋</li> 13 <li>許褚</li> 14 <li>徐晃</li> 15 <li>張遼</li> 16 </ul> 17 18 <!-- 插入JS代碼 --> 19 <script type="text/javascript"> 20 //獲取ul標簽 21 var ul=document.getElementById('ul'); 22 //因為li是ul內部的元素,根據事件冒泡原理,從內到外執行,點擊最里面的元素,最終會由內向外執行 23 //所有的注冊事件,最終會執行到ul,在ul中的注冊事件,根據傳遞過程中的傳遞數據,搭建事件委托,委托ul處理li的事件 24 ul.onclick=function(e){ 25 //在點擊的時候,清除所有的樣式 26 var lis=this.children; 27 for(var i=0;i<lis.length;i++){ 28 lis[i].style.backgroundColor=''; 29 } 30 //e 事件對象 31 // e.target 真正點擊的目標,是真正觸發事件的對象 32 e.target.style.backgroundColor='red'; 33 } 34 </script> 35 </body> 36 </html>
代碼分析:
在事件處理函數中,可以傳遞一個參數e,這個參數我們叫做事件對象,也叫事件參數。事件對象e是系統傳遞過去,事件函數也是系統調用的。系統調用事件函數的時候,會給事件函數傳遞一個參數,傳遞的參數具有具體值,可以在事件函數執行時獲取e中攜帶的值。
e:事件參數,也叫事件對象,可以寫作a,習慣上寫成e
e.target 真正觸發事件的對象
總結:事件委托簡化了以前給所有的li注冊事件的一個過程,只需要給這些元素的父元素注冊事件就好了。
**********************************************************************************************************************************************************************************
**********************************************************************************************************************************************************************************
二、事件對象e
通過事件對象e,可以獲得事件發生時一些和事件相關的數據(事件的一些屬性)。
例如:<input type='button' id='btn' value='按鈕'></input>
給按鈕注冊點擊事件,但是當給按鈕注冊完點擊事件后,如何獲取事件對象那?
var btn=document.getElementById('btn');
btn.onclick=function(e){}
DOM標准中,是給事件處理函數一個參數,就是給function一個參數e,e就是事件對象。這是標准方式。
在老版本的IE中獲取事件對象的方式是 window.event
所有事件對象e在瀏覽器中存在兼容性問題,處理方式:讓e始終是事件對象,如下:
e = e || window.event;
獲取了事件對象e后,我們想知道e里面有什么,或者說e怎么用那?
1.獲取事件階段 console.log(e.eventPhase) 獲取事件階段 1事件捕獲階段 2 事件目標階段 3事件冒泡階段
2.獲取事件真正出發的對象(事件源) e.target ,但是e.target存在瀏覽器兼容性問題,老版本IE中,是srcElement,解決辦法如下:
target = e.target || e.srcElemnet
3.獲取事件處理函數所在的對象 e.currentTargert e.currentTargert作用與this一樣,所有可以用this代替
如果沒有事件冒泡, e.currentTargert與e.target都是一樣的。
通過示例代碼具體分析,代碼如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>事件對象</title> 6 7 <style type="text/css"> 8 #box1{ 9 width: 300px; 10 height: 300px; 11 background-color: red; 12 } 13 #box2{ 14 width: 200px; 15 height: 200px; 16 background-color: green; 17 } 18 #box3{ 19 width: 100px; 20 height: 100px; 21 background-color: blue; 22 } 23 </style> 24 </head> 25 <body> 26 <div id="box1"> 27 <div id="box2"> 28 <div id="box3"></div> 29 </div> 30 </div> 31 32 33 <!-- 插入JS代碼 --> 34 <script type="text/javascript"> 35 // 獲取三個盒子id,並給三個盒子注冊點擊事件 36 var box1=document.getElementById('box1'); 37 var box2=document.getElementById('box2'); 38 var box3=document.getElementById('box3'); 39 var boxs=[box1,box2,box3]; 40 for(var i=0;i<boxs.length;i++){ 41 boxs[i].onclick=function(e){ 42 console.log(this.id);//點擊輸出各個盒子的id 43 console.log(e.target);//輸出出發點擊事件的盒子 44 console.log(e.currentTarget);//輸出點擊事件所在的對象 45 } 46 } 47 </script> 48 </body> 49 </html>
實際效果:
原始圖:
點擊藍色盒子結果圖:
上述結果分析:
事件最終反饋冒泡階段,即從內向外執行,依照box3---->box2---->box1順序執行點擊函數
box3: id:box3,觸發函數對象:<div id='box3'></div> 事件所在對象:<div id='box3'></div>
box2: id:box2,觸發函數對象:<div id='box3'></div> 事件所在對象:<div id='box2'></div>
box1: id:box1,觸發函數對象:<div id='box3'></div> 事件所在對象:<div id='box1'></div>
點擊綠色盒子結果圖:
上述結果分析:事件最終反饋冒泡階段,即從內向外執行,box2---->box1順序執行點擊函數
box2: id:box2,觸發函數對象:<div id='box2'></div> 事件所在對象:<div id='box2'></div>
box1: id:box1,觸發函數對象:<div id='box2'></div> 事件所在對象:<div id='box1'></div>
4.獲取事件處理函數名稱 e.type
作用:對於一個元素,可能有click mouseover mouseout事件等,如果一個一個定義,比較耗費內存,可以只定義一個函數,讓click mouseover mouseout指向該函數,在函數中使用switch-case加以判別,具體如下代碼所示:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>事件對象</title> 6 7 <style type="text/css"> 8 #box1{ 9 width: 100px; 10 height: 100px; 11 background-color: red; 12 } 13 </style> 14 </head> 15 <body> 16 <div id="box1"> 17 </div> 18 19 20 <!-- 插入JS代碼 --> 21 <script type="text/javascript"> 22 function fn(e){ 23 switch(e.type){ 24 case 'click': 25 console.log('這是一個點擊事件'); 26 break; 27 case 'mouseout': 28 console.log('這是鼠標移出事件'); 29 break; 30 case 'mouseover': 31 console.log('這是鼠標懸浮事件'); 32 } 33 } 34 // 獲取三個盒子id,並給三個盒子注冊點擊事件 35 var box1=document.getElementById('box1'); 36 box1.onclick=fn; 37 box1.onmouseout=fn; 38 box1.onmouseover=fn; 39 </script> 40 </body> 41 </html>
5.獲取鼠標在屏幕坐標
e.clientX
e.clientY 獲取鼠標相對於瀏覽器可視區坐標
e.pageX
e.pageY 獲取鼠標相當於整個文檔坐標