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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

详解浏览器事件捕获、冒泡

發布時間:2023/12/20 HTML 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解浏览器事件捕获、冒泡 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

事件委托/事件代理

包含幾個階段?

代碼演示

addEventListener第三個參數

e.target.nodeName 和 e.currentTarget.nodeName 區別

如何阻止事件的傳播?

現在有一個場景面試題

阻止事件默認行為

兼容性

封裝一個監聽的方法

封裝一個阻止事件的傳播的方法

封裝一個阻止事件默認行為的方法


事件委托/事件代理

包含幾個階段?

三個階段:捕獲階段 => 目標階段 => 冒泡階段

捕獲階段:
從上到下,從window到你點擊的目標節點,不如點擊一個 input
window?=> body?=> inpiut?=> body?=> window

代碼演示
?

<body><div id="parent" class="flex-center">parent<p id="child" class="flex-center">child<span id="son" class="flex-center"><a id="aTag" href="https://baidu.com">點我啊</a></span></p></div> </body> <script type="text/javascript">const parent = document.getElementById('parent'); const child = document.getElementById('child'); const son = document.getElementById('son'); const aTag = document.getElementById('aTag');aTag.addEventListener('click', function(e) {e.preventDefault(); // 阻止A標簽默認事件 })window.addEventListener('click', function(e) {// e.target.nodeName 和 e.currentTarget.nodeName 下面會講這兩個參數的意思console.log('window 捕獲', e.target.nodeName, e.currentTarget.nodeName); }, true); // addEventListener第三個參數 true代表在捕獲階段執行。false或者不填代表在冒泡階段執行。parent.addEventListener('click', function(e) {console.log('parent 捕獲', e.target.nodeName, e.currentTarget.nodeName); }, true);child.addEventListener('click', function(e) {console.log('child 捕獲', e.target.nodeName, e.currentTarget.nodeName); }, true);son.addEventListener('click', function(e) {console.log('son 捕獲', e.target.nodeName, e.currentTarget.nodeName); }, true);son.addEventListener('click', function(e) {console.log('son 冒泡', e.target.nodeName, e.currentTarget.nodeName); }, false);child.addEventListener('click', function(e) {console.log('child 冒泡', e.target.nodeName, e.currentTarget.nodeName); }, false);parent.addEventListener('click', function(e) {console.log('parent 冒泡', e.target.nodeName, e.currentTarget.nodeName); }, false);window.addEventListener('click', function(e) {console.log('window 冒泡', e.target.nodeName, e.currentTarget.nodeName); }, false); </script>

效果如下:

點擊span標簽時控制臺輸出信息如下:

addEventListener第三個參數

  • 默認值為冒泡
  • true:代表在捕獲階段執行
  • false或者不填:代表在冒泡階段執行

e.target.nodeName 和 e.currentTarget.nodeName 區別

  • e.target.nodeName:指當前點擊的元素
  • e.currentTarget.nodeName: 綁定事件監聽的元素

如何阻止事件的傳播?

e.stopPropagation();

注意:它不是阻止冒泡,而是阻止的事件的傳播!!!事件的捕獲和冒泡都會阻止掉!!!
在以上代碼的監聽 parent 點擊事件中加入?e.stopPropagation(); 會發生什么?

parent.addEventListener('click', function(e) {e.stopPropagation();console.log('parent 捕獲', e.target.nodeName, e.currentTarget.nodeName); }, true);

點擊span標簽時控制臺輸出信息如下:

我們在監聽 parent 點擊事件中加入?e.stopPropagation(); 阻止了事件傳播,走到 parent 事件時,當前事件已經觸發了所以會打印出? 「parent 捕獲 SPAN DIV」,但是會阻止后續事件的傳播。

如果在冒泡事件里面阻止事件的傳播呢?

child.addEventListener('click', function(e) {e.stopPropagation();console.log('child 冒泡', e.target.nodeName, e.currentTarget.nodeName); }, false);

捕獲階段沒做攔截,整個捕獲階段會完整的走完,但是冒泡階段到了child就會走完,因為我們在child里面攔截了它。

現在有一個場景面試題

問題:現在有一個頁面,這個頁面上有許多的元素,div p button 等,每個元素上都有自己的 click 事件,都不相同。
需求:一個用戶進入這個頁面的時候,會有一個狀態 banned,window.banned 。
true:表示當前用戶被封禁了,用戶點擊當點頁面上的任何元素,都不執行原有的click邏輯,而是 alert 彈窗,提示你被封禁了!!!

false:不做任何操作

答:在最上層捕獲事件中做攔截,比如window,如果banned為true,就直接在捕獲階段阻止事件傳播,并且彈窗提示,否則不進行任何操作。

window.addEventListener('click', function(e) {if(banned) {e.stopPropagation();alert('你被封禁了!!!');return} console.log('window 捕獲', e.target.nodeName, e.currentTarget.nodeName); }, true);

效果:當banned為true時,控制臺不會打印任何信息,會彈窗提示。未false?則不做任何操作;

阻止事件默認行為

e.preventDefault();

什么叫做默認行為

比如點擊a標簽會跳轉到另個頁面,比如拖拽到一張圖片到瀏覽器,瀏覽器會打開這個圖片,比如點擊表單提交按鈕,會提交當前表單……

如果我們不希望這些默認行為的發生,我們應該怎么做?

最開始寫的代碼中有個a標簽,點擊時是要跳轉到百度的

<a id="aTag" href="https://baidu.com">點我啊</a>

如果我們不想讓他跳轉到百度,在a標簽事件上做個攔截,當點擊 a標簽時,就不會跳轉到百度。

const aTag = document.getElementById('aTag');aTag.addEventListener('click', function(e) {e.preventDefault(); // 阻止a標簽默認事件 })

兼容性

屬性說明
addEventListener只支持 Firefox、Chrome、IE高版本、Safari、Opera
attachEvent兼容IE7、IE8

封裝一個監聽的方法

? ? ? ? 我們很難真正的去一個元素上加一個方法之類的,那樣要去操作原型鏈,先簡單通過一個類的方式去封裝。

class BomEvent {constructor(element) {this.element = element;}/*** @param { 事件類型 } type * @param { 事件觸發后的回調 } handler */addEvent(type, handler) { /*** 通過if判斷* 分別判斷 addEventListener、attachEvent、以及不存在它們的情況下去怎么做*/if(this.element.addEventListener) {/* 走冒泡形式,因為IE不支持事件的捕獲 */this.element.addEventListener(type, handler, false); } else if(this.element.attachEvent) {this.element.attachEvent(`on${type}`, handler)/*** 如果在attachEvent情況下考慮 IE7、IE8不支持箭頭函數的情況下* 把handler換成* function() { handler.call(element) };*/} else {/*** 可能有一些更奇怪的瀏覽器,attachEvent 都沒有* 我們直接給element上面綁定元素* 直接在 handler屬性上去綁*/this.element[`on${type}`] = handler;}}/*** 和 addEvent幾乎是一樣的* 只不過調用的API不同*/removeEvent(type, handler) {if(this.element.removeEventListener) {this.element.removeEventListener(type, handler, false); } else if(this.element.detachEvent) {this.element.detachEvent(`on${type}`, handler)} else {this.element[`on${type}`] = null;}} }

封裝一個阻止事件的傳播的方法

function stopPropagation(event) {if(event.stopPropagation) {event.stopPropagation(); // 標準 w3c瀏覽器} else {event.cancelBubble = true; // IE} }

封裝一個阻止事件默認行為的方法

function preventDefault(event) {if(event.preventDefault) {event.preventDefault(); // 標準 w3c瀏覽器} else {event.returnValue = false; // IE} }

總結

以上是生活随笔為你收集整理的详解浏览器事件捕获、冒泡的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。