1. 程式人生 > 實用技巧 >js的事件冒泡、捕獲、目標和事件的相容

js的事件冒泡、捕獲、目標和事件的相容

在js中,事件的寫法有三種,這也是件事的相容。
1.addEventListener

        var div=document.querySelector("div");
        div.addEventListener("click",clickHandler1);
        function clickHandler1(e){
            //e.stopPropogation();
            console.log(e)
        }
        div.addEventListener("click",clickHandler2);
        function clickHandler2(e){
            console.log("bbb")
        //this.removeEventListener("click",clickHandler)   刪除事件
        }

缺點:不支援IE8及以下
優點:支援捕獲和冒泡階段分開偵聽
支援事件拋發機制
支援同一個物件且同一個事件做多個事件回撥函式,如例中的clickHandler1,clickHandler2都可以執行
事件使用時可以將函式與內容完全分離
1.attachEvent

div.attachEvent("onclick",clickHandler);
 function clickHandler(e){
        console.log(e);
     //div.detachEvent("onclick",clickHandler);   刪除事件
  } 

缺點:IE8以上不支援,沒有捕獲,不支援一次點選({noce:true}) addEventListener的第四個引數,相當於刪除事件,前面的文章中說過。
優點:支援IE8以下,
並且可以同一個物件且同一個事件呼叫多個回撥函式
事件使用時可以將函式與內容完全分離
3.onclick

        div.onclick=function(){
            console.log("a");
        }
        div.onclick=function(){
            console.log("b");
        }   //只能列印  b  

優點:全瀏覽器支援,不考慮相容問題,
程式碼便捷
缺點:不支援事件拋發機制,只能使用系統預設事件
同一個元素同一個事件不支援多個回撥函式
因為程式碼大量使用匿名函式,容易造成回撥地獄,並且在開發中程式碼實際功能不能分離
上面內容說到了相容,下面是相容問題的寫法

            function addEventListen(elem,type,callback){   //elem是偵聽物件,type是事件型別,callback是回撥函式 ,刪除事件也是這樣相容
            try{                                            //可以不寫在函式內,直接 try  catch ,我只是習慣了寫在函式內
                elem.addEventListener(type,callback)
            }catch(e){
                elem.attachEvent("on"+type,callback);
            }
        }

事件的相容問題和事件說了後,就可以說冒泡、捕獲和目標了

假設現在有物件A,物件B,物件C,包含順序是A-->B-->C ,C在最裡層,三個物件都設定了偵聽,點選C時,執行順序:
A-->B-->C進入到裡層,這是捕獲階段,然後開始執行事件 C-->B-->A 這就是冒泡階段,找到C就是目標階段。
在只有一個物件時候,冒泡機制沒什麼影響,所以不用考慮,但是當物件包含物件時候,就必須要考慮到冒泡。
下面,程式碼示例

var div0=document.querySelector(".div0");
var div1=document.querySelector(".div1");
var div2=document.querySelector(".div2");
div0.addEventListener("click",div0ClickHandler);
div1.addEventListener("click",div1ClickHandler);
div2.addEventListener("click",div2ClickHandler,true);
function div0ClickHandler(e){
         //console.log(e);           
         console.log(e.currentTarget);//老版本瀏覽器
  }
function div1ClickHandler(e){
    console.log(e.currentTarget);       
    // e.stopPropagation();  //停止冒泡   新版本瀏覽器用
}
function div2ClickHandler(e){
    console.log(e.currentTarget);   
   }

可以看到,當點選最裡面的div2時,列印的時順序是div2-->div1-->div0 這就是冒泡
當div1加了阻止冒泡後,當點選最裡面的div2時,列印的就是 div2-->div1,因為冒泡阻止在div1了
第三個引數如果是true,就是捕獲,當點選後,在進去的時候就執行事件,比如div2加了true,不影響,還是div2-->div1-->div0
比如div0加了true,就是div0-->div2-->div1,在進去的時候執行了最外層。

html

<div class="div0">
         div0
<div class="div1"> div1
 <div class="div2"> div2</div>
</div>
</div>

css

  .div0
        {
            width:200px;
            height: 200px;
            background-color: aquamarine;
            position: relative;
            left:0;
            right: 0;
            margin: auto;
            border:1px solid #000000;
        }
        .div1
        {
            width: 130px;
            height: 130px;
            background-color: orange;
            position: absolute;
            left:0;
            right: 0;
            top:0;
            bottom: 0;
            margin: auto;
        }
        .div2
        {
            width: 50px;
            height: 50px;
            background-color: skyblue;
            position: absolute;
            left:0;
            right: 0;
            top:0;
            bottom: 0;
            margin: auto;
        }