DOM事件標准定義了兩種事件流,分別是捕獲和冒泡。默認情況下,事件使用冒泡事件流,不使用捕獲事件流。然而,在Firefox和Safari里,你可以顯式的指定使用捕獲事件流,方法是在注冊事件時傳入useCapture參數,將這個參數設為true。
冒泡事件流
當事件在某一DOM元素被觸發時,例如用戶在客戶名字節點上點擊鼠標,事件將跟隨着該節點繼承自的各個父節點冒泡穿過整個的DOM節點層次,直到它遇到依附有該事件類型處理器的節點,此時,該事件是onclick事件。在冒泡過程中的任何時候都可以終止事件的冒泡,在遵從W3C標准的瀏覽器里可以通 過調用事件對象上的stopPropagation()方法,在Internet Explorer里可以通過設置事件對象的cancelBubble屬性為true。如果不停止事件的傳播,事件將一直通過DOM冒泡直至到達文檔根。
捕獲事件流
事件的處理將從DOM層次的根開始,而不是從觸發事件的目標元素開始,事件被從目標元素的所有祖先元素依次往下傳遞。在這個過程中,事件會被從文檔 根到事件目標元素之間各個繼承派生的元素所捕獲,如果事件監聽器在被注冊時設置了useCapture屬性為true,那么它們可以被分派給這期間的任何 元素以對事件做出處理;否則,事件會被接着傳遞給派生元素路徑上的下一元素,直至目標元素。事件到達目標元素后,它會接着通過DOM節點再進行冒泡。
傳統的事件冒泡
傳統的阻止子元素繼承父元素的事件方法是:為子元素添加父元素的相同事件,然后在子元素事件中阻止事件冒泡。例如:在父元素中添加onclick事件,如果不阻止冒泡的話,點擊子元素也會響應父元素事件。而在子元素中阻止冒泡的話,則子元素不響應父元素事件。
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>Insert title here</title>
- <script type="text/javascript" src="jquery.min.js"></script>
- <script type="text/javascript">
- function test1(){
- $("#child").click(function(e){
- e.stopPropagation();
- });
- alert("測試1");
- }
- </script>
- </head>
- <body>
- <div id="parent" onclick="test1(this);" style="border:1px solid black;width:250px">
- <input type="text" value="123" id="child">
- </div>
- </body>
- </html>
特殊的事件冒泡
對於onmouseover和onmouseout事件,不能使用e.stopPropagation()或e.cancelBubble=true來阻止事件冒泡。雖然onmouseleave和onmouseenter事件可以替代onmouseover和onmouseout事件,因為這兩個事件是不會冒泡的。但是這兩個事件只支持IE瀏覽器。jQuery中有mouseleave事件個mouseenter事件,可以用bind綁定它們即可解決瀏覽器沖突。
純js的操作則需如下方式:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>Insert title here</title>
- <script type="text/javascript" src="jquery.min.js"></script>
- <script type="text/javascript">
- function isLeaveOrEnter(e,obj){
- if(e.type != "mouseover" && e.type != "mouseout"){
- return false;
- }
- var relag= relag?e.relatedTarget:(e.type=="mouseover")?e.toElement:e.formElement;
- if(relag && relag == obj){
- if(e.type == "mouseover"){
- $("#child").val("這是一次測試");
- }else{
- $("#child").val("");
- }
- }
- }
- </script>
- </head>
- <body>
- <div id="parent" onmouseover="isLeaveOrEnter(event,this);" onmouseout="isLeaveOrEnter(event,this);" style="border:1px solid black;width:250px">
- <input type="text" value="123" id="child">
- </div>
- </body>
- </html>
操作原理:
獲取事件作用的對象元素,判斷該對象是不是綁定的對象元素,如果是則進行操作,不是則不操作。這里的示例是當鼠標移入div時input框的值為“這是一次測試”,移除div時清空值,而鼠標移入input框時則不做操作。
return false也能阻止事件冒泡,但是它不僅阻止了事件冒泡也阻止了事件本身,相當於阻塞了該事件,不再執行。而e.stopPropagation()只是阻止事件冒泡。
默認操作
事件操作可以使用阻止冒泡,而鏈接跳轉等操作則需要阻止默認操作才行,這時需要用到event.preventDefault或window.event.returnValue=false。