JavaScript中不冒泡的DOM事件的使用小結
在前端開發(fā)中,DOM事件流(捕獲階段→目標階段→冒泡階段)是核心基礎之一。我們熟知的click、keydown、mouseover等事件,都會在觸發(fā)后從目標元素向上冒泡至父元素、document甚至window,這也是事件委托的核心原理。
但并非所有事件都遵循這一規(guī)則——有些事件僅在觸發(fā)的目標元素上生效,不會向上傳播,也就是所謂的**“不冒泡的事件”**。本文將系統(tǒng)梳理這類事件,解析其特性與應用場景,幫你避開開發(fā)中的常見坑。
一、為什么有些事件不冒泡?
事件是否冒泡,本質是由其設計初衷決定的:
- 冒泡事件的核心是“通用交互”(如點擊、鼠標移動),允許父元素統(tǒng)一處理子元素的同類事件,便于實現(xiàn)事件委托;
- 不冒泡事件多與“元素專屬狀態(tài)/資源加載”相關(如焦點、資源加載),這類事件的影響范圍僅局限于目標元素本身,向上傳播無實際意義。
例如focus(獲取焦點)事件,僅對輸入框、按鈕等可交互元素有意義。若允許冒泡,父元素會無差別接收到所有子元素的焦點變化,反而增加不必要的性能開銷和邏輯混亂。
二、常見的不冒泡事件及解析
1. focus / blur:焦點相關事件(核心不冒泡事件)
- focus:元素獲得焦點時觸發(fā)(如點擊輸入框、按Tab鍵切換焦點);
- blur:元素失去焦點時觸發(fā)(如點擊輸入框外區(qū)域、切換到其他元素)。
這兩個是最典型的不冒泡事件,也是前端開發(fā)中最常接觸的“非冒泡事件”。
開發(fā)提醒:若想監(jiān)聽子元素的焦點變化,不能依賴focus/blur的冒泡,可使用其“冒泡版替代事件”——focusin(對應focus)和focusout(對應blur),這兩個事件會正常冒泡,是focus/blur的官方替代方案。
示例代碼:
// ? 錯誤:父元素無法捕獲子元素的focus事件(不冒泡)
document.querySelector('.parent').addEventListener('focus', () => {
console.log('父元素捕獲focus'); // 不會執(zhí)行
});
?
// ? 正確:用focusin監(jiān)聽(冒泡)
document.querySelector('.parent').addEventListener('focusin', () => {
console.log('子元素獲取焦點'); // 正常執(zhí)行
});
2. load / unload:資源加載相關事件
load:資源加載完成時觸發(fā),常見于
img、script、audio、video等元素,僅在目標元素上觸發(fā),不會冒泡;unload:頁面/資源即將被卸載時觸發(fā)(如關閉標簽頁、導航到其他頁面),僅綁定在
window或目標元素上生效,無冒泡行為。
注意:window.onload是頁面所有資源加載完成的事件,雖綁定在window上,但本質也不屬于“冒泡事件”——它是全局事件,沒有傳播對象。
示例代碼:
// img加載完成事件(僅在img本身觸發(fā))
const img = document.querySelector('img');
img.addEventListener('load', () => {
console.log('圖片加載完成'); // 正常執(zhí)行
});
?
// ? 父元素無法捕獲img的load事件(不冒泡)
document.body.addEventListener('load', () => {
console.log('捕獲圖片load'); // 不會執(zhí)行
});
3. stop:媒體播放相關事件
stop事件僅在audio/video等媒體元素上觸發(fā),當媒體播放被主動停止時生效。該事件僅作用于觸發(fā)的媒體元素,無冒泡行為。例如點擊視頻的“停止”按鈕,僅該視頻元素觸發(fā)stop,其父容器不會接收到該事件。
4. readystatechange:文檔狀態(tài)變化事件
該事件在document.readyState改變時觸發(fā)(如從"loading"到"interactive"再到"complete"),僅綁定在document或XMLHttpRequest等對象上生效,不會向父元素傳播。常用于監(jiān)聽頁面DOM加載完成(作為DOMContentLoaded的補充方案)。
5. scroll:特殊的“條件冒泡”事件
scroll事件是特例:標準規(guī)范中scroll不冒泡,但部分瀏覽器(如Chrome)對其做了“冒泡兼容”——元素的scroll事件不會冒泡,而window的scroll事件是全局事件。
開發(fā)建議:若想監(jiān)聽滾動,建議直接綁定到滾動元素本身,而非依賴父元素捕獲。
三、如何處理不冒泡事件?
面對不冒泡事件,核心解決思路有三個:
1. 直接綁定到目標元素
針對focus/blur/load等事件,直接在觸發(fā)的元素上綁定監(jiān)聽函數(shù),是最直接、最可靠的方式。
2. 使用冒泡版替代事件
如focusin替代focus、focusout替代blur,利用冒泡特性實現(xiàn)父元素統(tǒng)一監(jiān)聽。
3. 利用事件捕獲階段處理
所有事件(包括不冒泡事件)都會經(jīng)過**“捕獲階段”**,可在捕獲階段監(jiān)聽不冒泡事件:
// 捕獲階段監(jiān)聽focus事件(即使不冒泡,也能被父元素捕獲)
document.querySelector('.parent').addEventListener('focus', () => {
console.log('捕獲階段捕獲focus'); // 正常執(zhí)行
}, true); // 第三個參數(shù)為true,代表在捕獲階段觸發(fā)
四、總結
不冒泡事件是DOM事件體系的重要組成部分,其設計符合**“事件影響范圍最小化”**的原則。核心要點可總結如下:
掌握這些特性,能幫你在事件委托、資源監(jiān)聽、焦點管理等場景中避開陷阱,寫出更健壯的前端代碼。
到此這篇關于JavaScript中不冒泡的DOM事件的使用小結的文章就介紹到這了,更多相關JavaScript不冒泡DOM內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JS實現(xiàn)獲取來自百度,Google,soso,sogou關鍵詞的方法
這篇文章主要介紹了JS實現(xiàn)獲取來自百度,Google,soso,sogou關鍵詞的方法,結合實例形式分析了js獲取來路頁面的方法與相關搜索引擎關鍵詞的處理技巧,需要的朋友可以參考下2016-12-12
JS實現(xiàn)Excel導出功能以及導出亂碼問題解決詳解
這篇文章主要為大家詳細介紹了JavaScript如何調用后臺接口實現(xiàn)Excel導出功能以及導出亂碼問題的解決辦法,需要的小伙伴可以參考一下2023-07-07
理解Javascript_06_理解對象的創(chuàng)建過程
在《理解Javascript_05_原型繼承原理》一文中已經(jīng)詳細的講解了原型鏈的實現(xiàn)原理,大家都知道原型鏈是基于對象創(chuàng)建的(沒有對象,哪來原型),那么今天就來解析一下對象的創(chuàng)建過程。2010-10-10
JavaScript?CSS解析B站的彈幕可以不擋人物原理及技巧
這篇文章主要為大家介紹了JavaScript?CSS解析B站的彈幕可以不擋人物原理及技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01

