日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js 事件流的事件冒泡和事件捕获与阻止事件传播

發(fā)布時間:2025/5/22 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js 事件流的事件冒泡和事件捕获与阻止事件传播 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為了方便引入事件流的概念,我們先來說說什么是事件。

事件就是用戶或瀏覽器自身執(zhí)行的某種動作。換句話說,我們在瀏覽網(wǎng)頁或者 APP 時,通常會在設(shè)備上產(chǎn)生很多交互性的操作,例如點擊、選擇、滾動屏幕、鍵盤輸入等等,這些交互性操作就是事件。

因為 DOM 結(jié)構(gòu)是一個樹型結(jié)構(gòu),所以當一個 HTML 元素產(chǎn)生一個事件時,該事件就會在元素結(jié)點與根節(jié)點之間按特定的順序傳播,路徑所經(jīng)過的節(jié)點都會收到該事件,這個事件傳播的過程就被稱為 事件流。

但是,當一個 HTML 元素產(chǎn)生一個事件時,是該元素最外層的父元素先收到事件并執(zhí)行,還是該元素本身先收到事件并執(zhí)行?

關(guān)于這個問題,IE 和 Netscape 開發(fā)團隊在開發(fā)初期提出了差不多完全相反的事件流概念。IE 的事件流是事件冒泡流,而 Netscape 的事件流是事件捕獲流

事件冒泡

IE的事件流叫做事件冒泡(event bubbling)。冒泡,顧名思義,事件像個水中的氣泡一樣一直往上冒,直到頂端。即事件開始時由具體的元素(文檔中嵌套層次最深的那個節(jié)點)接收,然后逐級向上傳播到較為不具體的節(jié)點(文檔)。以下面的 HTML 頁面為例:

<!DOCTYPE html> <html><head><title> Example </title></head><body><div class="one"></div></body> </html>

如果你單擊了頁面中的<div>元素,那么這個 click 事件會按照如下順序傳播:

  • <div>
  • <body>
  • <html>
  • document
  • 也就是說,click 事件首先在<div>元素上發(fā)生,而這個元素就是我們單擊的元素。然后,click 事件沿 DOM 樹向上傳播,在每一級節(jié)點上都會發(fā)生,直至傳播到 document 對象。下圖展示了事件 冒泡的過程。

    事件捕獲

    Netscape 團隊提出的另一種事件流叫做事件捕獲(event capturing)。事件捕獲的思想是不太具體的節(jié)點應(yīng)該更早接收到事件,而具體的節(jié)點應(yīng)該后接收到事件。事件捕獲的用意在于在事件到達預(yù)定目標之前捕獲它。如果仍以前面的 HTML頁面作為演示事件捕獲的例子,那么單擊<div> 元素就會以下列順序觸發(fā) click 事件。

  • document
  • <html>
  • <body>
  • <div>
  • 在事件捕獲過程中,document 對象首先接收到 click 事件,然后事件沿DOM樹依次向下,一直 傳播到事件的實際目標,即<div>元素。下圖展現(xiàn)了事件捕獲的過程。

    DOM 事件流

    后來,ECMAScript 標準重新將事件流規(guī)范為三個階段,分別為事件捕獲階段,處于目標階段,事件冒泡階段。首先發(fā)生的是事件捕獲,為截取事件提供了機會。然后是實際的目標接受到事件。最后一個階段是冒泡階段,可以在這個階段對事件做出響應(yīng)。以前面的 HTML 頁面為例。點擊<div>元素會按照下圖所示順序觸發(fā)事件。

    雖然大部分的瀏覽器都遵循著標準,但是在IE瀏覽器中,事件流卻是非標準的。在IE中事件流只有兩個階段:處于目標階段,冒泡階段。如下圖所示:

    還有另外一個需要注意的地方,標準的事件流中所有的事件都要經(jīng)過捕捉階段和目標階段,但是有些事件會跳過冒泡階段。例如,讓元素獲得輸入焦點的 focus 事件以及失去輸入焦點的 blur 事件就都不會冒泡。

    阻止事件流

    為什么要阻止事件流

    事件就是用戶或瀏覽器自身執(zhí)行的某種動作。諸如 點擊、加載 和鼠標滑過。而響應(yīng)某個事件的函數(shù)就叫做事件處理函數(shù)(又叫事件監(jiān)聽函數(shù)、事件句柄)。

    因為事件流的存在,當某個元素的父元素或者子元素與當前元素擁有相同的事件處理函數(shù)時一個問題就暴露了出來。

    為了更好的說明這個問題,我們把前面的那個簡單的 HTML 拿來重新改造一下。

    <!DOCTYPE html> <html> <head><title> Example </title><style>.one {width: 100px;height: 100px;background-color: #00F;cursor: pointer;}</style> </head> <body><div class="one"></div><script>const html = document.querySelector('html');const body = document.body;const div = document.querySelector('.one');document.onclick = Event => {alert("我是:document");}html.onclick = Event => {alert("我是:html");}body.onclick = Event => {alert("我是:body");}div.onclick = Event => {alert("我是:div");}</script> </body> </html>

    我們期望的是當點擊 div 時彈出 “我是:div”,然而...

    這就是事件流附帶的一個弊端,在事件冒泡階段, <div> 的 click 事件向上傳播到根節(jié)點,除了觸發(fā)自己的事件處理函數(shù)之外,還順帶觸發(fā)了上級元素上的 click 事件處理函數(shù)。

    也就是說,當一個元素與父元素或祖元素擁有相同的事件,該元素的事件處理函數(shù)被觸發(fā)時,父元素和祖元素相同的事件也會被觸發(fā)。

    如何阻止事件流

    換句話說,為了避免頁面交互操作出現(xiàn)異常,當一個元素設(shè)置一個事件后,它的子元素或者父元素就不能設(shè)置同樣的事件。很顯然,這樣的結(jié)果并不是我們想要的。難道就沒有什么解決的方法么?答案是肯定的:有。

    W3C 中有一個 stopPropagation() 事件方法。該方法將停止事件的傳播,阻止它被分派到其他 Document 節(jié)點。但是這是一個 DOM 2 級方法,IE 不出意外的不支持,IE 的方法是 e.cancelBubble=true。

    我們把上邊示例的 javascript 代碼拿過來改一下,看看效果如何。

    <script>const html = document.querySelector('html');const body = document.body;const div = document.querySelector('.one');html.onclick = Event => {window.event ? window.event.cancelBubble = true : e.stopPropagation();alert("我是:html");}body.onclick = Event => {window.event ? window.event.cancelBubble = true : e.stopPropagation();alert("我是:body");}div.onclick = Event => {window.event ? window.event.cancelBubble = true : e.stopPropagation();alert("我是:div");}</script>

    不錯,這才是我們想要的效果。

    參考

  • JavaScript高級程序設(shè)計(第3版)尼古拉斯 · 澤拉斯 著
  • w3school--TML DOM Event 對象:http://www.w3school.com.cn/jsref/dom_obj_event.asp
  • 淺談前端和移動端的事件機制:https://juejin.im/post/59ede91ef265da43143fde87#heading-1
  • 轉(zhuǎn)載于:https://www.cnblogs.com/wangdapang/p/10500602.html

    總結(jié)

    以上是生活随笔為你收集整理的js 事件流的事件冒泡和事件捕获与阻止事件传播的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。