本節要點:1.干預系統的事件處理機制
(一)DOM事件流
(二)停止事件冒泡
(三)阻止事件的默認行為
1.干預系統的事件處理機制
(一)DOM事件流
DOM模型是一個樹形結構,在DOM模型中,HTML元素是有層次的。當一個HTML元素上產生一個事件時,該事件會在DOM樹中元素節點與根節點之間按特定的順序傳播,路徑所經過的節點都會收到該事件,這個傳播過程就是DOM事件流。
DOM事件標准定義了兩種事件流,分別是捕獲事件和冒泡事件。
1.冒泡事件流
默認情況下,事件使用冒泡事件流。當事件(例如單擊事件)在某一DOM元素上被觸發時,事件將沿着該節點的各個父結點冒泡穿過整個DOM節點層次。在冒泡過程中的任何時候都可以終止事件的冒泡。如果不停止事件的傳播,事件將一直通過DOM冒泡直至到達文檔根。
(冒泡往上走)
2.捕獲事件流
於冒泡模型相反,在捕獲事件流模型中,事件的處理將從DOM層次的根開始,而不是從觸發事件的目標元素開始,事件被從目標元素的所有所有祖先元素依次往下傳遞。在這個過程中,事件會被從文檔的根到事件目標元素之間各個繼承派生的元素所捕獲。
(捕獲往下走)
3.DOM標准的事件模型
DOM標准同時支持捕獲事件模型和冒泡事件模型,但是,捕獲事件模型先發生。兩種事件流都會觸發DOM中的所有對象,從document對象開始,也在document對象結束。
4.事件傳導的3個階段
(1)事件捕捉(Capturing)階段:事件將沿着DOM樹向下傳送,經過目標節點的每一個祖先節點,直至目標節點。例如,用戶單擊了一個超鏈接,則該單擊事件將從document節點轉送到html元素、body元素以及包含該鏈接的p元素。目標節點就是觸發事件的DOM節點。
(2)目標(target)階段:在此階段中,事件傳導到目標節點。瀏覽器在查找到已經指定給目標事件的監聽器后,就會運行該監聽器。
(3)冒泡(Bubbling)階段:事件將沿着DOM樹向上轉送,再次逐個訪問目標元素的祖先節點直到document節點。該過程中的每一步,瀏覽器都將檢測那些不是捕捉事件監聽器的事件監聽器並執行它們。(即:與觸發事件無關的事件監聽器也由於冒泡將被執行)。
(二)停止事件冒泡
當事件(例如單擊事件)在某一DOM元素上被觸發時,事件將沿着該節點的各個父節點冒泡穿過整個DOM節點層次,直到遇到依附有該事件類型處理器的節點。
<!DOCTYPE html> <html> <head> <title>Test</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="style.css"> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> function doSometing(obj,evt){ alert(obj.id); // 做瀏覽器兼容 var e = (evt)? evt:window.event; //獲取IE或非IE瀏覽器的事件 if (window.event) { //如果是IE瀏覽器 e.cancelBubble = true; //IE瀏覽器,設置該屬性為true,取消事件冒泡 }else{ e.stopPropagation(); //非IE瀏覽器,該方法取消事件的進一步捕獲或冒泡。 } } </script> </head> <body> <div id="parent1" onclick="alert(this.id);" style="width: 250px;background-color: #cacaca"> <p>This is parent1 div</p> <div id="child1" onclick="alert(this.id);" style="width: 200px;background-color: orange"> <p>This is child1.Will bubble.</p> </div> </div> <br> <div id="parent2" onclick="alert(this.id);" style="width: 250px;background-color: cyan;"> <p>This is parent2 div</p> <div id="child2" onclick="doSomething(this,event);" style="width: 200px;background-color: #aeaeae"> <p>This is child2.</p> </div> </div> </div> </body> </html> |
如圖所示,以上代碼定義了4個div,其中2個父div,2個子div。單擊每個div都會彈出一個消息框,顯示其id。單擊child1和child2時,事件會冒泡傳導到其父元素parent1和parent2。因此,單擊child1會彈出兩個消息框。而單擊child2時,會調用doSomethig函數,使用cancelBubble屬性或stopPropagation()方法來停止事件冒泡。
(三)阻止事件的默認行為
事件的默認行為是指瀏覽器在事件傳遞和處理完成后自動執行的與該事件關聯的默認動作。例如,單擊一個超鏈接的默認行為是訪問其定義的url。
IE和其他瀏覽器阻止事件的默認行為的方法不同。在IE中,可以通過設置event對象的returnValue屬性為false來阻止事件的默認行為;在其他瀏覽器中,則可以通過設置event對象的preventDefault()方法來實現。
<!DOCTYPE html> <html> <head> <title>Test</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="style.css"> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> window.onload = function(){ var test = document.getElementById('test'); test.onclick = function(e){ //當單擊此超鏈接時執行這個函數 alert('URL:' + this.href + ',不會跳轉'); stopDefault(e); } } function stopDefault(e){ if(e && e.preventDefault){ //判斷瀏覽器是非IE瀏覽器 e.preventDefault(); //非IE瀏覽器下使用preventDefault方法 }else{ //IE瀏覽器下令事件(window.event)的returnValue屬性為false; window.event.returnValue = false; } return false; } </script> </head> <body> <a href="http://www.baidu.com" id="test">百度</a> </body> </html> |
可以通過event對象的preventDefault屬性來判斷瀏覽器是否支持preventDefault()方法。如果preventDefault屬性值為true則表示支持,否則不支持。