1. 程式人生 > 實用技巧 >JS的事件冒泡和事件捕獲

JS的事件冒泡和事件捕獲

DOM事件流三個階段

1.事件捕獲:當滑鼠觸發DOM事件時,瀏覽器會從根節點由外到內進行事件傳播。即觸發子元素的事件,父元素會通過事件捕獲的方式優先觸發父元素的事件。

2.目標階段:正在處理事件。

3.事件冒泡:與事件捕獲相反,瀏覽器會從子節點由內到外進行事件傳播。

DOM事件流處理順序:先捕獲,再冒泡。

具體區別

通常在addEventListener方法的第三個引數中設定true則為事件捕獲,false則為事件冒泡,預設為false。

html程式碼:

    <div id="div1">
        <div id="div2">
        </
div> </div>

css程式碼:

<style>
    #div1 {
        width: 500px;
        height: 500px;
        border: 1px solid #ffffff;
        background: blanchedalmond;
    }

    #div2 {
        width: 200px;
        height: 200px;
        border: 1px solid #ffffff;
        background: blue;
    }
</style>

js程式碼:

<script> letdiv1=document.getElementById("div1"); letdiv2=document.getElementById("div2"); div1.addEventListener('click',function(){ console.log('div1--捕獲'); },true); div2.addEventListener('click',function(){ console.log('div2--捕獲'); },true); div1.addEventListener('click',function(){ console.log('div1--冒泡'); }); div2.addEventListener('click',function(){ console.log('div2--冒泡'); }); </script>

點選div2打印出的結果:

由此可證上述結論即:捕獲先於冒泡;對於捕獲而言,外層先於內層(div1先於div2列印);對於冒泡而言,內層先於外層(div2先於div1列印)。

而我們期望的其實是對於冒泡事件,希望點選div2時僅僅只打印出div2--冒泡,修改js為:

<script>
    let div1 = document.getElementById("div1");
    let div2 = document.getElementById("div2");
    div1.addEventListener('click', function (e) {
        console.log('div1--冒泡');
    });
    div2.addEventListener('click', function (e) {
        console.log('div2--冒泡');
        e.stopPropagation();
    });
</script>

此時點選div2列印的結果:

相容問題

IE瀏覽器9以下不支援e.stopPropagation();來取消冒泡事件,在IE瀏覽器10版本以上中已經解決該問題:

為了更好的相容各個瀏覽器版本,對e.stopPropagation()事件進行一個判斷:

<script>
    let div1 = document.getElementById("div1");
    let div2 = document.getElementById("div2");
    div1.addEventListener('click', function (e) {
        console.log('div1--冒泡');
    });
    div2.addEventListener('click', function (e) {
        console.log('div2--冒泡');
        stopBubble();
    });
    function stopBubble (e) {
        if (e && e.stopPropagation) {
            e.stopPropagation();
        } else {
            window.event.cancelBubble = true;
        }
    }
</script>