JS事件順序(捕獲與冒泡)

問(wèn)題:

如果一個(gè)元素和它的祖先元素注冊(cè)了同一類型的事件函數(shù)(例如點(diǎn)擊等), 那么當(dāng)事件發(fā)生時(shí)事件函數(shù)調(diào)用的順序是什么呢?
比如, 考慮如下嵌套的元素:

<div class="outer">
    <div class="inner"></div>
</div>

兩個(gè)元素都有onclick的處理函數(shù). 如果用戶點(diǎn)擊了inner, inner和outer上的事件處理函數(shù)都會(huì)被調(diào)用. 但誰(shuí)先誰(shuí)后呢?

事件流:

事件流描述的是從頁(yè)面中接受事件的順序扶欣,但有意思的是暴凑,微軟(IE)和網(wǎng)景(Netscape)開發(fā)團(tuán)隊(duì)居然提出了兩個(gè)截然相反的事件流概念,IE的事件流是事件冒泡流(event bubbling),而Netscape的事件流是事件捕獲流(event capturing)枫攀。

事件捕獲(event capturing)

網(wǎng)景公司提出的事件流叫事件捕獲流。

事件捕獲流的思想是不太具體的DOM節(jié)點(diǎn)應(yīng)該更早接收到事件鸵赖,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件抚恒,針對(duì)上面同樣的例子,點(diǎn)擊按鈕巡蘸,那么此時(shí)click事件會(huì)按照這樣傳播:(下面我們就借用addEventListener的第三個(gè)參數(shù)來(lái)模擬事件捕獲流)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>
        <button>
            <p>點(diǎn)擊捕獲</p>
        </button>
    </div>
    <script>
        var oP=document.querySelector('p');
        var oB=document.querySelector('button');
        var oD=document.querySelector('div');
        var oBody=document.querySelector('body');

        oP.addEventListener('click',function(){
            console.log('p標(biāo)簽被點(diǎn)擊')
        },true);
    
        oB.addEventListener('click',function(){
            console.log("button被點(diǎn)擊")
        },true);

        oD.addEventListener('click',  function(){
            console.log('div被點(diǎn)擊')
        },true);

        oBody.addEventListener('click',function(){
            console.log('body被點(diǎn)擊')
        },true);
    </script>
</body>
</html>

同樣我們看一下后臺(tái)的打印結(jié)果:


image.png

正如我們看到的奋隶,它是和冒泡流萬(wàn)全相反,從最不具體的元素接收到最具體的元素接收事件 body=>div=>button=>p

事件冒泡(event bubbling)

與事件捕獲相反, 事件開始時(shí)由最具體的元素接收悦荒,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body onclick="bodyClick()">
    <div onclick="divClick()">
        <button onclick="btn()">
            <p onclick="p()">點(diǎn)擊冒泡</p>
        </button>
    </div>
    <script>
       function p(){
          console.log('p標(biāo)簽被點(diǎn)擊')
       }
        function btn(){
            console.log("button被點(diǎn)擊")
        }
         function divClick(event){
             console.log('div被點(diǎn)擊');
         }
        function bodyClick(){
            console.log('body被點(diǎn)擊')
        }
    </script>
</body>
</html>

點(diǎn)擊p元素打印結(jié)果:


image.png
DOM事件流:

DOM事件分0級(jí)和2級(jí):
1唯欣、0級(jí)分兩種:

  • 行內(nèi)事件:在標(biāo)簽中寫事件
<input type="button" id="btn" value="按鈕" onclick="alert('123')">
  • 元素.on事件名=函數(shù)
document.getElementById("btn").onclick = function () {
    alert('123');
}
事件沒(méi)有1級(jí)DOM

2、DOM2級(jí)事件:添加和移除事件處理程序:addEventListener()和removeEventListener()搬味。

DOM2級(jí)(addEventListener)事件流包含3個(gè)階段境氢,事件捕獲階段、處于目標(biāo)階段碰纬、事件冒泡階段萍聊。 先(document)開始一路向下捕獲, 直到達(dá)到目標(biāo)元素, 其后再次從目標(biāo)元素開始冒泡.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
    <button id="btn">DOM事件流</button>
    <script>
        var btn=document.getElementById("btn");
        btn.onclick=function(event){
            console.log("div 處于目標(biāo)階段");
        };
        document.body.addEventListener("click",function(event){
            console.log("event bubble 事件冒泡");
        },false);
        document.body.addEventListener("click",function(event){
            console.log("event catch 事件捕獲");
        },true);
    </script>
</body>
</html>

打印結(jié)果為:


image.png

就是這樣一個(gè)流程,先捕獲悦析,然后處理寿桨,然后再冒泡出去。

作為開發(fā)者, 可以決定事件處理器是注冊(cè)在捕獲或者是冒泡階段. 如果addEventListener的最后一個(gè)參數(shù)是true, 那么處理函數(shù)將在捕獲階段被觸發(fā); 否則(false)默認(rèn)冒泡, 會(huì)在冒泡階段被觸發(fā).

阻止冒泡事件:

w3c的方法是e.stopPropagation()强戴,IE則是使用e.cancelBubble = true

參考鏈接: 淺談js的事件冒泡和事件捕獲

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末亭螟,一起剝皮案震驚了整個(gè)濱河市挡鞍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌预烙,老刑警劉巖墨微,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異扁掸,居然都是意外死亡翘县,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門也糊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)炼蹦,“玉大人,你說(shuō)我怎么就攤上這事狸剃∑” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵钞馁,是天一觀的道長(zhǎng)虑省。 經(jīng)常有香客問(wèn)我,道長(zhǎng)僧凰,這世上最難降的妖魔是什么探颈? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮训措,結(jié)果婚禮上伪节,老公的妹妹穿的比我還像新娘。我一直安慰自己绩鸣,他們只是感情好怀大,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著呀闻,像睡著了一般化借。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捡多,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天蓖康,我揣著相機(jī)與錄音,去河邊找鬼垒手。 笑死蒜焊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的科贬。 我是一名探鬼主播山涡,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了鸭丛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤唐责,失蹤者是張志新(化名)和其女友劉穎鳞溉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鼠哥,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡熟菲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朴恳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抄罕。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖于颖,靈堂內(nèi)的尸體忽然破棺而出呆贿,到底是詐尸還是另有隱情,我是刑警寧澤森渐,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布做入,位于F島的核電站,受9級(jí)特大地震影響同衣,放射性物質(zhì)發(fā)生泄漏竟块。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一耐齐、第九天 我趴在偏房一處隱蔽的房頂上張望浪秘。 院中可真熱鬧,春花似錦埠况、人聲如沸耸携。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)违帆。三九已至,卻和暖如春金蜀,著一層夾襖步出監(jiān)牢的瞬間刷后,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工渊抄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尝胆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓护桦,卻偏偏與公主長(zhǎng)得像含衔,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • ??JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的。 ??事件杭隙,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,490評(píng)論 1 11
  • 背景知識(shí) 什么是事件哟绊?直觀的說(shuō)就是網(wǎng)頁(yè)上發(fā)生的事情,大部分是指用戶的鼠標(biāo)動(dòng)作和鍵盤動(dòng)作痰憎,如點(diǎn)擊票髓、移動(dòng)鼠標(biāo)、按下某個(gè)...
    吧啦啦小湯圓閱讀 1,846評(píng)論 2 15
  • JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的铣耘。事件洽沟,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定的交互瞬...
    threetowns閱讀 342評(píng)論 0 0
  • JavaScript 程序采用了異步事件驅(qū)動(dòng)編程模型。在這種程序設(shè)計(jì)風(fēng)格下蜗细,當(dāng)文檔裆操、瀏覽器、元素或與之相關(guān)的對(duì)象發(fā)...
    劼哥stone閱讀 1,256評(píng)論 3 11
  • JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的鳄乏。事件跷车,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定的交互瞬...
    LemonnYan閱讀 679評(píng)論 0 4