上個星期在微博中一個關於javascript捕獲和冒泡代碼的討論,可能沒有動手實現一篇的人沒法給出肯定的答案。javascript
這裏再來回顧一下以前的三條微博。html
事件的執行順序java
JavaScript冒泡和捕獲考察題目看圖回答問題,晚上公佈答案。瀏覽器
問:點擊Li,JS的執行順序是什麼?函數
JavaScript捕獲和冒泡探討code
總結就是:先捕獲,後冒泡,捕獲從上到下,冒泡從下到上(形象點說法:捕獲像石頭沉入海底,冒泡則像氣泡冒出水面)htm
問:假如去掉註釋 event.stopPropagation(); 結果又會輸出什麼?對象
答:去掉event.stopPropagation()
以後,因爲事件有捕獲和冒泡時先執行捕獲,捕獲到div以後,事件被阻止,後面就不在繼續傳播了。因此只輸出divcallback.事件
在上面的代碼若是增長一個div.addEventListener('click',callbackdiv2,false);ip
則div先執行捕獲,接着執行上面這句冒泡,因此微博裏的一個朋友評論說事件執行過捕獲就不會執行冒泡實際上是不對的。
div.addEventListener('click',callbackdiv,true);這一句只能是捕獲才執行。
以上代碼代碼:演示
事件不一樣瀏覽器處理函數
element.addEventListener(type, listener[, useCapture]); // IE6~8不支持(捕獲和冒泡經過useCapture,默認false) element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持(只執行冒泡事件) element[’on’ + type] = function(){} // 全部瀏覽器(默認執行冒泡事件)
JavaScript捕獲和冒泡探討
W3C規範中定義了3個事件階段,依次是捕獲階段、目標階段、冒泡階段。事件對象按照上圖的傳播路徑依次完成這些階段。若是某個階段不支持或事件對象的傳播被終止,那麼該階段就會被跳過。舉個例子,若是Event.bubbles屬性被設置爲false,那麼冒泡階段就會被跳過。若是Event.stopPropagation()在事件派發前被調用,那麼全部的階段都會被跳過。
捕獲 階段:
在事件對象到達事件目標以前,事件對象必須從window通過目標的祖先節點傳播到事件目標。 這個階段被咱們稱之爲捕獲階段。在這個階段註冊的事件監聽器在事件到達其目標前必須先處理事件。
目標 階段:
事件對象到達其事件目標。 這個階段被咱們稱爲目標階段。一旦事件對象到達事件目標,該階段的事件監聽器就要對它進行處理。若是一個事件對象類型被標誌爲不能冒泡。那麼對應的事件對象在到達此階段時就會終止傳播。
冒泡 階段:
事件對象以一個與捕獲階段相反的方向從事件目標傳播通過其祖先節點傳播到window。這個階段被稱之爲冒泡階段。在此階段註冊的事件監聽器會對相應的冒泡事件進行處理。
在一個事件完成了全部階段的傳播路徑後,它的Event.currentTarget會被設置爲null而且Event.eventPhase會被設爲0。Event的全部其餘屬性都不會改變(包括指向事件目標的Event.target屬性).
跨瀏覽器的事件處理函數:
var EventUtil = { addHandler: function(element, type, handler) { if (element.addEventListener) { // DOM2 element.addEventListener(type, handler, false); } else if (element.attachEvent) { // IE element.attachEvent('on' + type, handler); } else { // DOM0 element['on' + type] = handler; } }, removeHandler: function(element, type, handler) { if (element.removeEventListener) { element.removeEventListener(type, handler, false); } else if (element.detachEvent) { element.detachEvent('on' + type, handler); } else { element['on' + type] = null; } } };
跨瀏覽器的事件對象:
var EventUtil = { getEvent: function(e) { return e ? e : window.e; }, getTarget: function(e) { return e.target || e.srcElement; }, preventDefault: function(e) { if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } }, stopPropagation: function(e) { if (e.stopPropagation) { e.stopPropagation() } else { e.cancelBubble = true; } } }
能夠看我以前寫過的一篇文章:如何中止冒泡和阻止默認行爲
ps:半個月沒發文章,由於我最近在搞這個:開發頭條網,而後我發現這個東西作好和作壞根本沒有出路,我考慮要不要下掉,嗚嗚……,請賜予我動力吧。