7.事件冒泡和事件捕獲(同一個DOM元素,注冊兩個事件,一個冒泡事件,一個捕獲事件,執行幾次?先執行哪個?)

這個問題的整理是基于面試題:
給同一個DOM元素綁定兩個事件,一個用冒泡,一個用捕獲,會執行幾次?先執行冒泡還是先執行捕獲?

例子:

<div id="outer"> 
    <p id="inner">Click me!</p>
</div>

事件冒泡:

微軟提出了名為事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻為把一顆石頭投入水中,泡泡會一直從水底冒出水面。也就是說,事件會從最內層的元素開始發生,一直向上傳播,直到document對象。
因此上面的例子在事件冒泡的概念下發生click事件的順序應該是p -> div -> body -> html -> document

事件捕獲:

網景提出另一種事件流名為事件捕獲(event capturing)。與事件冒泡相反,事件會從最外層開始發生,直到最具體的元素。
上面的例子在事件捕獲的概念下發生click事件的順序應該是document -> html -> body -> div -> p

如下代碼,有四個div嵌套元素,均綁定了click事件,addEventListener函數的第三個參數設置為false說明不為捕獲事件,即為冒泡事件。該代碼執行結果如下:
點擊one元素,輸出one;
點擊two元素,輸出two one;
點擊three元素,輸出 three two one;
點擊four元素,輸出 four three two one;

<div id='one'>
        <div id='two'>
            <div id='three'>
                <div id='four'>
                </div>
            </div>
        </div>
    </div>
<script>

    var one=document.getElementById('one');
    var two=document.getElementById('two');
    var three=document.getElementById('three');
    var four=document.getElementById('four');

    one.addEventListener('click',function(){
        alert('one');
    },false);
    two.addEventListener('click',function(){
        alert('two');
    },false);
    three.addEventListener('click',function(){
        alert('three');
    },false);
    four.addEventListener('click',function(){
        alert('four');
    },false);
</script>

而捕獲則相反。當觸發目標元素時,會從目標元素的最頂層的祖先元素事件往下執行到目標元素為止。
將上面的代碼第三個參數均改為true,則執行結果如下:
點擊one,輸出one;
點擊two,輸出one two;
點擊three,輸出one two three;
點擊four,輸出one two three four;
很明顯執行順序是不同的。

問題解釋:

無論是冒泡事件還是捕獲事件,元素都會先執行捕獲階段
從上往下,如有捕獲事件,則執行;一直向下到目標元素后,從目標元素開始向上執行冒泡元素

如下代碼:
此時點擊four元素,four元素為目標元素,one為根元素祖先,從one開始向下判斷執行。
one為捕獲事件,輸出one;
two為冒泡事件,忽略;
three為捕獲時間,輸出three;
four為目標元素,開始向上冒泡執行,輸出four;(從此處分為兩部分理解較容易。)
three為捕獲已執行,忽略;
two為冒泡事件,輸出two;
one為捕獲已執行,忽略。
最終執行結果為:one three four two

one.addEventListener('click',function(){
        alert('one');
    },true);
    two.addEventListener('click',function(){
        alert('two');
    },false);
    three.addEventListener('click',function(){
        alert('three');
    },true);
    four.addEventListener('click',function(){
        alert('four');
    },false);

執行次數:綁定了幾個事件便執行幾次。

如下代碼,two元素綁定了兩個不同事件,點擊two都會執行這兩個事件。而執行順序有所差異
1、如果two為目標元素,目標元素的事情按順序執行,而其他元素根據W3C的標準執行,即先捕獲后冒泡。
點擊two執行結果:one(因為是two的父元素支持捕獲事件所以先執行) two,bubble two,capture(順序執行,注意逗號不是間隔,是輸出內容。)
2、如果目標元素不是two,則two的兩個事件按先捕獲后冒泡觸發執行,也就是跟前面討論的執行過程是一樣的,只不過兩個事件都綁定在同一個DOM元素上。
點擊three執行結果:one two,capture three,capture two,bubble

one.addEventListener('click',function(){
        alert('one');
    },true);
    two.addEventListener('click',function(){
        alert('two,bubble');
    },false);
    two.addEventListener('click',function(){
        alert('two,capture');
    },true);
    three.addEventListener('click',function(){
        alert('three,capture');
    },true);
    four.addEventListener('click',function(){
        alert('four,capture');
    },true);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容