在一個對象上觸發某類事件(好比單擊onclick事件),若是此對象定義了此事件的處理程序,那麼此事件就會調用這個處理程序,若是沒有定義此事件處理程序或者事件返回true,那麼這個事件會向這個對象的父級對象傳播,從裏到外,直至它被處理(父級對象全部同類事件都將被激活),或者它到達了對象層次的最頂層,即document對象(有些瀏覽器是window)。javascript
打個比方說:你在地方法院要上訴一件案子,若是地方沒有處理此類案件的法院,地方相關部門會幫你繼續往上級法院上訴,好比從市級到省級,直至到中央法院,最終使你的案件得以處理。html
(1)事件冒泡容許多個操做被集中處理(把事件處理器添加到一個父級元素上,避免把事件處理器添加到多個子級元素上),它還可讓你在對象層的不一樣級別捕獲事件。java
【集中處理例子】程序員
<div onclick="eventHandle(event)" id="outSide" style="width:100px; height:100px; background:#000; padding:50px"> <div id="inSide" style="width:100px; height:100px; background:#CCC"></div> </div> <script type="text/javascript"> //本例子只在外面盒子定義了處理方法,而這個方法同樣能夠捕獲到子元素點擊行爲並處理它。假設有成千上萬子元素要處理,難道咱們要爲每一個元素加「onclick="eventHandle(event)"」?顯然沒有這種集中處理的方法來的簡單,同時它的性能也是更高的。 function eventHandle(e) { var e=e||window.event; var obj=e.target||e.srcElement; alert(obj.id+' was click') } </script>
(2)讓不一樣的對象同時捕獲同一事件,並調用本身的專屬處理程序作本身的事情,就像老闆一下命令,各自員工作本身崗位上的工做去了。瀏覽器
【同時捕獲同一事件例子】ide
<div onclick="outSideWork()" id="outSide" style="width:100px; height:100px; background:#000; padding:50px"> <div onclick="inSideWork()" id="inSide" style="width:100px; height:100px; background:#CCC"></div> </div> <script type="text/javascript"> function outSideWork() { alert('My name is outSide,I was working...'); } function inSideWork() { alert('My name is inSide,I was working...'); } //由於下面程序自動激活單擊事件,有些瀏覽器不容許,因此請單擊灰色盒子,從這裏開始下命令,這樣由於冒泡的緣由,黑色大盒子也會收到單擊事件,並調用了本身的處理程序。若是還有更多盒子嵌套,同樣道理。 /* function bossOrder() { document.getElmentById('inSide').click(); } bossOrder(); */ </script>
●事件捕獲其實有三種方式,事件冒泡只是其中的一種:(1)IE從裏到外(inside→outside)的冒泡型事件。(2)Netscape4.0從外到裏(outside→inside)的捕獲型事件。(3)DOM事件流,先從外到裏,再從裏到外回到原點(outside→inside→outside)的事件捕獲方法(彷佛對象將觸發兩次事件處理,這有什麼做用?鄙人不懂!)。函數
●不是全部的事件都能冒泡。如下事件不冒泡:blur、focus、load、unload。性能
●事件捕獲方式在不一樣瀏覽器,甚至同種瀏覽器的不一樣版本中是有所區別的。如Netscape4.0採用捕獲型事件解決方案,其它多數瀏覽器則支持冒泡型事件解決方案,另外DOM事件流還支持文本節點事件冒泡。this
●事件捕獲到達頂層的目標在不一樣瀏覽器或不一樣瀏覽器版本也是有區別的。在IE6中HTML是接收事件冒泡的,另外大部分瀏覽器將冒泡延續到window對象,即……body→documen→window。google
●阻止冒泡並不能阻止對象默認行爲。好比submit按鈕被點擊後會提交表單數據,這種行爲無須咱們寫程序定製。
一般狀況下咱們都是一步到位,明確本身的事件觸發源,並不但願瀏覽器自做聰明、漫無目的地去幫咱們找合適的事件處理程序,即咱們明確最精準目標,這種狀況下咱們不須要事件冒泡。另外經過對事件冒泡的理解,咱們知道程序將作多較多額外的事情,這必然增大程序開銷。還有一個重要的問題是:事件冒泡處理可能會激活咱們原本不想激活的事件,致使程序錯亂,甚至無從下手調試,這常成爲對事件冒泡不熟悉程序員的棘手問題。因此必要時,咱們要阻止事件冒泡。
【不想激活的事件被激活例子】
<div onclick="openWin('http://www.baidu.com')" id="outSide" style="width:100px; height:100px; background:#000; padding:50px"> <div onclick="openWin('http://www.google.com')" id="inSide" style="width:100px; height:100px; background:#CCC"></div> </div> <script type="text/javascript"> //本例你實際但願點擊灰色盒子打開google首頁,而點擊黑色盒子打開baidu首頁,但結果你點擊灰色盒子的時候,倒是同時打開了兩個網頁。其實在實際設計中較少遇到此問題,你可能會想若是我在頁面不一樣DOM深處安置了不一樣的按鈕或連接,深層處的事件觸發會不會波及頂層的按鈕呢?不會,由於按鈕不能造成嵌套關係。 function openWin(url) { window.open(url); } </script>
下面是本人在網上抄的一個方法,把這個方法放在精準目標對象處理程序結尾,本事件觸發處理結束後,事件將不在進行冒泡處理。
【阻止事件冒泡例子】
<div onclick="showMsg(this,event)" id="outSide" style="width:100px; height:100px; background:#000; padding:50px"> <div onclick="showMsg(this,event)" id="inSide" style="width:100px; height:100px; background:#CCC"></div> </div> <script type="text/javascript"> //阻止事件冒泡後,你點擊灰色盒子,整個過程只彈一次對話框了(注意與默認狀況對比) function showMsg(obj,e) { alert(obj.id); stopBubble(e) } //阻止事件冒泡函數 function stopBubble(e) { if (e && e.stopPropagation) e.stopPropagation() else window.event.cancelBubble=true } </script>