冒泡和捕獲

?在瀏覽器中,事件的傳播方式分為:事件冒泡和事件捕獲蓉冈。那么事件冒泡和事件捕獲分別是什么城舞?為什么會出現(xiàn)兩種傳播方式呢轩触?

一、前提

  1. 在瀏覽器中用戶點擊鼠標家夺,操作系統(tǒng)最先知道脱柱,瀏覽器次之。
  2. 頁面中子元素被點擊了拉馋,意味著父元素也被點擊榨为。
  3. 如果子元素和父元素同時監(jiān)聽了點擊事件,那么點擊子元素后煌茴,是子元素先知道随闺,還是父元素先知道。而這個知道的前后順序景馁,就是由事件傳播方式?jīng)Q定的板壮。

二逗鸣、冒泡模式和捕獲模式

?事件的傳播途徑是通過文檔節(jié)點組成的有序列表合住。在DOM里面,這個事件傳播路徑的最后一點就是事件對象(Event Target)本身撒璧,其之前的元素就是事件對象的祖先元素透葛。

  • 觸發(fā)事件后:
    • 對于冒泡模式,事件首先被事件對象本身知道卿樱,然后讓其父元素知道僚害,就這樣在祖先元素中一層層向外傳播,直至window 對象繁调,如果中間有節(jié)點設(shè)置監(jiān)聽這個事件萨蚕,就調(diào)用其監(jiān)聽函數(shù)。
    • 對于捕獲模式蹄胰,事件首先被window 對象知道岳遥,然后到document 節(jié)點,最后才被事件對象本身知道裕寨,如果中間有節(jié)點監(jiān)聽此事件浩蓉,就調(diào)用監(jiān)聽函數(shù)。
      例子:
<html>
        <head>
            <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
            <meta charset="utf-8">
            <title>example</title>
        </head>
        <body>
            <ul>
                <li>item1</li>
                <li>item2</li>
                <li class="clicked">item3</li>
            </ul>
        </body>
    </html>
  • 在上面例子的結(jié)構(gòu)中宾袜,假設(shè)我在item3 用鼠標點擊了一下捻艳。
    • 在捕獲模式中,事件是按以下順序傳播的:window --> document --> <html> --> <body> --> <ul> --> <li class="clicked">,如果有節(jié)點監(jiān)聽點擊事件庆猫,那么就在傳播到那個節(jié)點的時候調(diào)用事件函數(shù)认轨。
    • 在冒泡模式中,事件的傳播順序是同捕獲模式相反的:<li class="clicked"> --> <ul> --> <body> --> <html> --> document --> window,如果有節(jié)點監(jiān)聽點擊事件月培,那么就在傳播到那個節(jié)點的時候調(diào)用事件函數(shù)嘁字。

三昨稼、設(shè)置冒泡模式或捕獲模式

?在十幾年前,那時候瀏覽器各自為政拳锚,其中一個巨頭網(wǎng)景公司主張捕獲模式假栓,所以那時它的瀏覽器只支持捕獲模式;而另一巨頭微軟公司支持冒泡模式霍掺,所以IE 9 以前的版本只支持冒泡模式匾荆。在2000 年的時候,w3c 將兩種模式都寫入標準里面杆烁,所以現(xiàn)在大部分瀏覽器都支持兩種模式牙丽。

?我們可以使用addEventListener(type, listener, useCapture) 方法來設(shè)置事件的傳播模式,如果想要捕獲模式兔魂,就將第三個參數(shù)useCapture 設(shè)為true 烤芦。如果想要冒泡模式,可以將第三個參數(shù)設(shè)為false 或者直接省略第三個參數(shù)析校,因為不傳入?yún)?shù)的時候构罗,參數(shù)值為undefined

? 例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JS Bin</title>
</head>
<body>
    <div>1
        <div>2
            <div>3
                <div>4
                    <div>5</div>
                </div>
            </div>
        </div>
    </div>
    <section id="alog"></section>
    <script>
        var divs = document.getElementsByTagName('div');
        function capture() {
            log('capture: ' + this.firstChild.nodeValue.trim())
        }
      
        function bubble() {
            log('bubble: ' + this.firstChild.nodeValue.trim())
        }

        for (var i = 0; i < divs.length; i++) {
            divs[i].addEventListener('click', capture, true);
            divs[i].addEventListener('click', bubble, false);
        }

        function log(msg) {
            var p = document.createElement('p');
            p.textContent = msg;
            alog.appendChild(p);
        }
    </script>
</body>
</html>

下圖是我點擊div 5 的結(jié)果

?

?在兩種模式混用的情況下智玻,如果是事件對象(Event Target)的父元素遂唧,按先捕獲后冒泡的順序進行。如果是事件對像自身吊奢,那么誰先監(jiān)聽就先執(zhí)行誰盖彭。在實際工作中不推薦混用兩種模式。

?例子:對上面代碼進行小小的改動

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JS Bin</title>
</head>
<body>
    <div>1
        <div>2
            <div>3
                <div>4
                    <div>5</div>
                </div>
            </div>
        </div>
    </div>
    <section id="alog"></section>
    <script>
        var divs = document.getElementsByTagName('div');
        function capture() {
            log('capture: ' + this.firstChild.nodeValue.trim())
        }
      
        function bubble() {
            log('bubble: ' + this.firstChild.nodeValue.trim())
        }

        for (var i = 0; i < divs.length; i++) {
/* 只是調(diào)換了下面兩句語句的位置*/
            divs[i].addEventListener('click', bubble, false); 
            divs[i].addEventListener('click', capture, true);
//  其他語句不變
        }

        function log(msg) {
            var p = document.createElement('p');
            p.textContent = msg;
            alog.appendChild(p);
        }
    </script>
</body>
</html>

下圖是我點擊div 5 的結(jié)果

鏈接

本文部分借鑒自: https://stackoverflow.com/a/4616720/7309659
部分來自饑人谷老師方方的觀點: http://www.reibang.com/users/b4fd9acca45c/timeline
饑人谷鏈接:https://jirengu.com/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末页滚,一起剝皮案震驚了整個濱河市召边,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裹驰,老刑警劉巖隧熙,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邦马,居然都是意外死亡贱鼻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門滋将,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邻悬,“玉大人,你說我怎么就攤上這事随闽「阜幔” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛾扇。 經(jīng)常有香客問我攘烛,道長,這世上最難降的妖魔是什么镀首? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任坟漱,我火速辦了婚禮,結(jié)果婚禮上更哄,老公的妹妹穿的比我還像新娘芋齿。我一直安慰自己,他們只是感情好成翩,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布觅捆。 她就那樣靜靜地躺著,像睡著了一般麻敌。 火紅的嫁衣襯著肌膚如雪栅炒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天术羔,我揣著相機與錄音赢赊,去河邊找鬼。 笑死聂示,一個胖子當(dāng)著我的面吹牛域携,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鱼喉,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼趋观!你這毒婦竟也來了扛禽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤皱坛,失蹤者是張志新(化名)和其女友劉穎编曼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剩辟,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡掐场,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了贩猎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熊户。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吭服,靈堂內(nèi)的尸體忽然破棺而出嚷堡,到底是詐尸還是另有隱情,我是刑警寧澤艇棕,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布蝌戒,位于F島的核電站串塑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏北苟。R本人自食惡果不足惜桩匪,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望友鼻。 院中可真熱鬧吸祟,春花似錦、人聲如沸桃移。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽借杰。三九已至过吻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蔗衡,已是汗流浹背纤虽。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绞惦,地道東北人逼纸。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像济蝉,于是被迫代替她去往敵國和親杰刽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

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