當你在瀏覽器上點擊一個按鈕時,點擊的事件不只僅發生在按鈕上,同時點擊的還有這個按鈕的容器元素,甚至也點擊了整個頁面。html
事件流描述了從頁面接收事件的順序,但在瀏覽器發展到第四代時,瀏覽器開發團隊提出了兩種徹底相反的事件流。瀏覽器
冒泡事件流:IE提出的事件流,即事件由最具體的元素接收,逐級向上,傳播到頁面。函數
捕獲事件流:Netscape提出的事件流,即事件由頁面元素接收,逐級向下,傳播到最具體的元素。post
兩種事件流在DOM2級事件模型中獲得了統一,相較於DOM0級事件模型,DOM2級有着以下特色:學習
一、容許在某個元素上綁定多個同類型的事件測試
二、規定了事件流的三個階段:捕獲階段、目標階段、冒泡階段url
【測試】使用addEventListener輸出事件流過程:spa
分別在window、document、html、body、btn上綁定事件,單擊按鈕,輸出結果以下[FF測試]orm
能夠看到當事件處於目標階段時,並不僅觸發一次,而是分別屬於捕獲和冒泡兩個階段。htm
儘管DOM2級事件規定了事件的三個階段,但遺憾的是,IE8及如下瀏覽器只支持冒泡事件流。
【測試】使用attachEvent輸出事件流過程:
分別在window、document、html、body、btn上綁定事件,單擊按鈕,輸出結果以下[IE8測試]
能夠看到僅輸出了目標和冒泡階段的信息,而且綁定在window上的事件並無被觸發,IE8及如下瀏覽器的冒泡事件僅冒泡到document
目前支持以attachEvent綁定事件的瀏覽器:IE6-10
經過前面的講述,能夠知道在事件流中,某元素的事件被觸發,同時也會致使其容器元素上的同類型事件被觸發。但不少時候,咱們並不但願這樣的結果。
此時能夠經過stopPropagation()或cancelBubble來阻止事件向下一級元素傳遞。
stopPropagation()是W3C標準下阻止事件傳遞的方法
【測試】使用addEventListener綁定,測試stopPropagation():
分別在box0-2上綁定事件,單擊box0,輸出結果[FF測試]
因爲addEventListener能夠設置是否在捕獲階段運行,故可分爲[在捕獲階段阻止事件傳遞]和[在冒泡階段阻止事件傳遞]
一、在捕獲階段阻止事件傳遞
二、在冒泡階段阻止事件傳遞
經過測試,能夠看到當阻止事件傳遞後,事件流將不會繼續執行。
【測試】使用attachEvent綁定,測試stopPropagation():
分別在box0-2上綁定事件,單擊box0,輸出結果[IE8測試]
因爲attachEvent不支持捕獲事件流,故僅冒泡階段測試其對stopPropagation()的支持程度:
能夠看到attachEvent的event對象不支持stopPropagation()方法
cancelBubble是IE標準下阻止事件傳遞的屬性,設置cancelBubble=true表示阻止冒泡
【測試】使用addEventListener綁定,測試cancelBubble:
分別在box0-2上綁定事件,單擊box0,輸出結果
一、在捕獲階段阻止:
[FF測試]
[Chrome測試]
[IE11測試]
能夠看到,只有在FF上的結果是咱們指望的結果,此外,經過對Safari、Opera進行測試,輸出結果與Chrome一致;對IE9-10進行測試,輸出結果與IE11一致
二、在冒泡階段阻止:
FF、Chrome、Safari、Opera、IE9-11均輸出上圖結果。
【測試】使用attachEvent綁定,測試cancelBubble:
分別在box0-2上綁定事件,單擊box0,輸出結果[IE8測試]
綜合測試結果,總結stopPropagation()及cancelBubble兼容性以下:
element.on[type] = triggerFn | addEventListener | attachEvent | ||
在冒泡階段阻止 | 在捕獲階段阻止 | 在冒泡階段阻止 | 在冒泡階段阻止 | |
stopPropagation() | 除IE8及如下,其餘均支持,且結果正確 | 支持,且結果正確 | 支持,且結果正確 | 不支持 |
cancelBubble | 支持,且結果正確 | 支持,但只有FF正確 | 支持,且結果正確 | 支持,且結果正確 |
使用時須要注意如下幾點:
一、雖然阻止事件傳遞分爲W3C標準(stopPropagation())和IE標準(cancelBubble),但並不意味着該屬性或方法爲各自瀏覽器所所獨有。測試代表,FF、Chrome等高級瀏覽器一樣支持IE標準下的cancelBubble。
二、若須要在捕獲階段阻止事件傳遞,使用addEventListener()進行事件監聽,同時使用e.stopPropagation()阻止冒泡。
三、若須要在冒泡階段阻止事件傳遞,在兼容addEventListener()和attachEvent()的同時,爲保險起見,須要對阻止事件傳遞方式進行兼容。如下僅表示在DOM2及事件模型下兼容方式:
一些元素在通常狀態下存在默認行爲,如:
對配置了href的<a>綁定單擊事件fn1,點擊後會首先執行fn1,但以後也會執行<a>標籤的默認行爲,即:跳轉href指向的頁面。
對<form>中的<input type="submit">綁定單擊事件fn2,點擊後首先會執行fn2,以後再執行<input type="submit">的默認行爲,即:提交表單數據。
爲解決元素默認事件對綁定事件的影響,咱們能夠採用event對象提供的方法進行處理。
preventDefault()是W3C標準下阻止元素默認事件的方法。
【測試】使用DOM0事件模型進行綁定,測試preventDefault():
在<a htrf = "http://www.baidu.com">上綁定單擊事件,點擊<a>,輸出結果[FF]:
點擊連接後,輸出「點擊了<a>」,且頁面不進行跳轉,說明阻止事件成功。
測試兼容性後發現,僅IE8及如下瀏覽器不支持preventDetault()
【測試】使用DOM2事件模型addEventListener進行綁定,測試preventDefault():
在<a htrf = "http://www.baidu.com">上綁定單擊事件,點擊<a>,輸出結果[FF]:
測試發現,對於支持addEventListener的瀏覽器,不管捕獲仍是冒泡階段均可以阻止默認事件。
【測試】使用DOM2事件模型attachEvent進行綁定,測試preventDefault():
在<a htrf = "http://www.baidu.com">上綁定單擊事件,點擊<a>,輸出結果[IE8]:
測試發現,對於支持attachEvent的瀏覽器,均不支持e.preventDefault()
returnValue是IE標準下阻止元素默認事件的方法,設置returnValue = false表示阻止默認事件。
【測試】使用DOM0事件模型進行綁定,測試returnValue:
在<a htrf = "http://www.baidu.com">上綁定單擊事件,點擊<a>,輸出結果[FF]:
點擊連接後,輸出「點擊了<a>」,但頁面進行跳轉,說明阻止事件失敗。
測試兼容性後發現,IE八、Chrome、Safari、Opera設置returnValue=false時,會阻止元素的默認事件;而FF、IE9-11則不會阻止。
【測試】使用DOM2事件模型addEventListener進行綁定,測試returnValue:
在<a htrf = "http://www.baidu.com">上綁定單擊事件,點擊<a>,輸出結果[FF]:
測試發現,對於支持addEventListener的瀏覽器:
在捕獲階段:FF、IE9-11不會阻止默認事件,而Chrome、Opera、Safari會阻止。
在冒泡階段:IE9-11不會阻止默認事件,而FF、Chrome、Opear、Safari會阻止。
【測試】使用DOM2事件模型attachEvent進行綁定,測試returnValue:
在<a htrf = "http://www.baidu.com">上綁定單擊事件,點擊<a>,輸出結果[IE8]:
測試發現,對於支持attachEvent的瀏覽器,returnVaule=false能夠阻止默認事件。
綜合測試結果,preventDefault和returnValue的兼容性以下(T:支持該屬性或事件且結果正確;F:不支持該屬性或事件或結果不正確:—:不支持該事件綁定方式):
函數名 | 事件綁定方式 | 事件流 | FF | Chrome | Opera | Safari | 模擬IE8 | 模擬IE9 | 模擬IE10 | IE11 |
---|---|---|---|---|---|---|---|---|---|---|
preventDetault() | element.on[type] = fn | 冒泡 | T | T | T | T | F | T | T | T |
addEventListener() | 捕獲 | T | T | T | T | — | T | T | T | |
冒泡 | T | T | T | T | — | T | T | T | ||
attachEvent() | 冒泡 | — | — | — | — | F | F | F | — | |
returnValue=false | element.on[type] = fn | 冒泡 | F | T | T | T | T | F | F | F |
addEventListener() | 捕獲 | F | T | T | T | — | F | F | F | |
冒泡 | F | T | T | T | — | F | F | F | ||
attachEvent() | 冒泡 | — | — | — | — | T | F | F | — |
使用時須要注意如下幾點:
一、爲兼容不一樣瀏覽器,可編寫以下代碼:
但實際上,這樣也存在着雷區,對於IE9和IE10,支持addEventListener和attachEvent進行事件綁定,而對照上表,IE9和IE10在使用attachEvent進行綁定時,沒法阻止默認事件。故應在事件綁定兼容時,優先檢驗addEventListener。
二、之前一直將returnValue = false與return false混淆,此處應注意returnValue是IE標準下Event對象的屬性,僅用於阻止元素的默認事件。而return false的做用範圍更加普遍,如:阻止事件、跳出循環、返回對象等等,方便的一刀切容易出錯,不可濫用。