事件||事件流||通用事件偵聽器函數

事件||事件流||通用事件偵聽器函數

一、跨瀏覽器事件對象:

事件流:描述的是從頁面中接收事件的順序。

IE:的事件流是事件冒泡流。javascript

事件冒泡(event bubbling):事件由最具體的元素(嵌套最深的那個節點)接收,而後逐級向上傳播到不具體的節點(文檔)。明顯的缺點就是在多個子元素上綁定事件,父元素節點會接受到全部的事件綁定,這是個很坑爹的體驗。html

Netscape Communicator:的事件流是事件捕獲流。java

事件捕獲(event capuring):是不太具體的元素節點應該更早的接收到事件,而更具體的節點應該最後接收到事件。符合經常使用的模型和思考方式。chrome

Dom事件流:「Dom2級事件」規定了事件流包括三個階段。(事件代理處理)瀏覽器

事件捕獲階段、處於事件階段和事件冒泡階段即事件捕獲爲截獲事件提供了機會接着實際的目標接收到事件最後冒泡階段,在這個階段對事件作出響應dom

實際上這裏已經顯示了捕獲要在冒泡以前。函數

大多的時候會把事件流添加到冒泡階段,這樣能夠最大限度的兼容各類瀏覽器。此時DOM2級事件設爲false。this

這裏的捕獲階段不涉及事件目標。這個時候的事件冒泡或者是事件捕獲使用,添加事件最後的限定true(捕獲階段)||false(冒泡階段)來觸發。若是不寫是根據瀏覽器的特性來實現的。url

以下來驗證:一個DOM元素綁定兩個事件,一個冒泡,一個捕獲,則事件會執行多少次,執行順序如何。先捕獲後冒泡。spa

//以下事件冒泡階段觸發
<div id='one'>1
  <div id='two'>2
    <div id='three'>3
      <div id='four'>4
      </div>
    </div>
  </div>
</div>
<script type='text/javascript'>
  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>

//點擊4,依次會觸發four、three、two、one。
<div id='one'>1
  <div id='two'>2
    <div id='three'>3
      <div id='four'>4
      </div>
    </div>
  </div>
</div>
<script type='text/javascript'>
  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');
  },true);//表示在捕獲階段觸發事件
  two.addEventListener('click',function(){
    alert('two');
  },true);
  three.addEventListener('click',function(){
    alert('three');
  },true);
  four.addEventListener('click',function(){
    alert('four');
  },true);
</script>
//點擊4則依次觸發:one、two、three、four
<div id='one'>1
  <div id='two'>2
    <div id='three'>3
      <div id='four'>4
      </div>
    </div>
  </div>
</div>
<script type='text/javascript'>
  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');
    },true);
    two.addEventListener('click',function(){
      alert('two,bubble');
    },false);//這裏的事件在冒泡階段觸發
    two.addEventListener('click',function(){
      alert('two,capture');
    },true);//這裏的事件在捕獲階段觸發
    three.addEventListener('click',function(){
      alert('three,bubble');
    },true);
    four.addEventListener('click',function(){
      alert('four');
    },true);
</script>
<!-- 執行順序最終結果是:(chrome先捕獲後冒泡)點擊4,依次會觸發 one、two,capture、three,bubble、four、two,bubble-->
<!-- 說明,同一個元素上綁定事件是先捕獲,再冒泡。中間還有一個處於目標階段 -->

二、事件處理程序(事件偵聽器):

事件是用戶或瀏覽器自身執行的某種動做:如click、load、mouseover等,響應某個事件的函數稱爲事件處理程序(事件監聽器)

一、html事件處理程序

事件處理程序中的代碼在執行時,有權訪問全局做用域中的任何代碼(匿名函數的做用域-全局)。

直接寫在頁面元素中,強耦合,摒棄。頁面在前解析,js在後解析。

存在時差問題,可能在處理程序解析以前就觸發了事件,會致使錯誤。

MouseEvent對象以下:

<input type="button" value = "click me" onclick = "console.log(event)"/>

這裏的path保存着事件冒泡的順序(具體到不具體),target保存着目標節點的信息,view保存着window對象的一些信息。

二、Dom0級事件處理程序(onclick): 

經過JavaScript指定事件處理程序的傳統方式,就是將一個函數賦值給一個事件處理程序屬性。這種方法被稱爲事件處理程序賦值,出如今第四代 Web 瀏覽器中。

每一個元素(包括 window 和 document)都有本身的事件處理程序屬性,屬性一般所有小寫,如 onclick。將這種屬性的值設置爲一個函數,就能夠指定事件處理程序。

<input type="button" value = "Dom0" id = "myBtn" />
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(event){
        console.log(event);
    }
</script>

打印結果與上邊無差。處理函數內部this指向元素節點。能夠取到this.id。

刪除事件,將事件處理函數置爲null便可。

btn.onclick = null;

三、Dom2級事件處理程序(事件綁定與取消綁定):

「DOM2級事件」定義了兩個方法,用於處理指定和刪除事件處理程序的操做:addEventListener()和removeEventListener() ;

它們接受3個參數:

  1. 要處理的事件名

  2. 做爲事件處理程序的函數

  3. 一個布爾值:

    true: 捕獲階段調用事件處理程序

    false: 冒泡階段調用

<input type="button" value = "Dom2" id = "myBtn2" />
<script type="text/javascript">
    var btn = document.getElementById("myBtn2");
    btn.addEventListener("click",function(event){
        alert("Dom2");
        console.log(event);
    },false);
</script>

事件event與以前的無差。

能夠添加多個事件,添加多個事件的時候,按添加的順序依次執行。

移除事件要一一對應,注意因爲匿名函數在內存中沒有指向對象,因此添加以後沒法移除因此作好的作法就是先定義好聲明的處理函數(或者函數表達式),在進行綁定和刪除。

大部分時候都是把事件添加到冒泡(false)階段,這樣能夠最大限度的兼容各類瀏覽器。

四、IE事件處理程序: 

IE 實現了與 DOM 中相似的兩個方法:attachEvent()和detachEvent() 

接受兩個參數:事件處理程序名稱、事件處理程序函數 

經過這種方法添加的事件處理程序會被添加到冒泡階段。 

<input type="button" value = "IE" id = "myBtn3" />
<script type="text/javascript">
    var btn = document.getElementById("myBtn3");
    btn.attachEvent("onclick",function(event){
        alert("Clicked");
        console.log(event);
        console.log(this)
    });
</script>

打印的結果不能展開:

在IE中使用 attachEvent() 與使用 DOM0 級方法的主要區別在於事件處理程序的做用域。

DOM0 級方法:在Dom0級事件當中,事件處理程序會在其所屬的元素的做用於內運行。

attachEvent()方法:使用attachEvent()方法的狀況下,事件處理程序會在全局做用域中運行。此時this 等於window。

固然,匿名函數不能被移除。

五、事件對象:

觸發Dom上的某個事件的時候,會產生一個事件對象event,這個對象包含着與事件相關的信息,包含致使事件的元素、事件的類型及其餘信息。

event對象包含着與建立它的特定事件有關的屬性和方法。

Dom中的事件對象:

事件對象的一些屬性和方法:

主要的有:

cancelable:代表是否能夠取消事件默認行爲。

currentTarget:時間處理程序當前正在處理的那個元素處理程序內部,對象this始終等於currentTarget的值。而target只包含事件的實際目標。

preventDefault():取消事件的默認行爲

target:事件目標。

stopPropagation(): 取消事件進一步的捕獲或者冒泡

只有在執行事件期間,event才存在,事件執行完成以後,event對象就會被銷燬。

IE事件對象中有區別的地方:

三、通用事件監聽函數

//寫一個通用的事件偵聽器函數 //跨瀏覽器事件對象
var EventUtil = {
    //頁面加載完成以後,頁面徹底加載以後執行。
    readyEvent:function(fn){  
        if(document.addEventListener){      
            //標準瀏覽器  
            document.addEventListener('DOMContentLoaded',function(){  
                //註銷事件,避免反覆觸發  
                document.removeEventListener('DOMContentLoaded',arguments.callee,false); 
                //執行函數   
                fn();
            },false);  
        }else if(document.attachEvent){     
            //IE瀏覽器  
            document.attachEvent('onreadystatechange',function(){  
                if(document.readyState=='complete'){  
                    document.detachEvent('onreadystatechange',arguments.callee);  
                    //執行函數   
                    fn();  
                }  
            });  
        }  
    },
    /*
     *attachEvent可使用匿名函數,但這樣以後,detachEvent將沒法卸載之。
     *detachEvent所卸載的函數必須使用函數名。
     */
    //添加事件
    addEvent:function(element,type,handler){
        if(element.addEventListener){//非IE,DOM2
            //事件類型、須要執行的函數、是否捕獲
            element.addEventListener(type,handler,false);
        }else if(element.attachEvent){//IE
            element.attachEvent('on'+type,handler);
        }else{
            element['on'+type] = handler;//DOM0
        }
    },
    //移除事件
    removeEvent:function(element,type,handler){
        if(element.removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detach('on'+type,handler);
        }else{
            element['on'+type] = null;
        }
    },
    //阻止事件冒泡(主要是事件冒泡,由於IE不支持事件捕獲),用於當即中止事件在Dom層中的傳播,即進一步取消事件的捕獲或者冒泡。
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation();//W3C標準
        }else{
            event.canceBubble = true;//IE
        }
    },
    //取消事件的默認行爲, 如url的跳轉等
    preventDefault:function(event){
        if(event.preventDefault){
            event.preventDefault();//W3C標準
        }else{
            event.returnValue = false;//IE
        }
    },
    //獲取事件目標
    getTarget:function(event){
        return event.target||event.srcElement;
    },
    //獲取event對象的引用,獲取事件的全部信息,確保隨時能使用event;
    getEvent:function(event){
        var event = event||window.event;//在Dom0級事件添加,event做爲window對象的一個屬性存在。
    }
};
// 定義一個函數處理多種類型的事件
var handler = function(event){
    switch(event.type){
        case "click":
            alert("Clicked");
            break;
        case "mouseover":
            event.target.style.backgroundColor = "red";
            break;
        case "mouseout":
            event.target.style.backgroundColor = "";
            break;
        default:
            alert("test switch");
    }
};
//阻止事件冒泡的實例
var btnCancel = document.getElementById("btnCancel");
btnCancel.onclick = function(event){
    alert("clicked222");    
    //這樣以後,body上的事件就不會觸發了,否則點一下,就會觸發這兩個事件。
    EventUtil.stopPropagation(event);
};

document.body.onclick = function(event){
    //若是btnCancle上阻止了事件冒泡,那麼body上的事件就不會被添加到btnCancle上。
    alert("body clicked")
}
獲取一組元素的序號,原理是本身先要獲取元素而後添加屬性到標籤中。點擊事件的時候再獲取自定義的屬性。
兩種方法,標籤添加屬性和使用自定義屬性。
另:Dom0型事件的處理函數的this 等於 event.target屬性。

<ul >
    <li class="a1">1</li>
    <li class="a2">2</li>
    <li class="a3">3</li>
    <li class="a4">4</li>
    <li class="a5">5</li>
    <li class="a6">6</li>
</ul>

var list = document.getElementsByTagName("li");
for(var i = 0,len = list.length;i<len;i++){
    list[i].index = i;//方法1,比較好
    list[i].setAttribute("data-index",i);//方法2
    list[i].onclick = function(event){
        console.log(this.getAttribute("data-index"));
        console.log(this.index);
        console.log(event);
        console.log(this==event.target);
    }
}

//固然事件也是能夠綁定到父元素上
var ul = document.getElementsByTagName("ul");
ul[0].onclick = function(event){
    console.log(event.target.index);
}

IE事件與FF(DOM)事件的區別:

一、window.event

表示當前的事件對象,IE的事件對象是window對象的一個屬性。 FF:沒有window.event對象。能夠經過給函數的參數傳遞event對象。如onmousemove=domousemove(event)。

二、獲取事件源

IE:srcElement;FF:target;

三、添加刪除事件方法不一樣

IE:element.attachEvent("onclick",function(){})

FF: element.addEventListener("click",function(){},false);

刪除事件也是不一樣的。

四、自定義DOM事件

自定義DOM事件不是由DOM原生觸發的,目的是讓開發人員建立本身的事件。建立自定義事件,須要調用createEvent("CustomEvent");

且看以下實例:

var div = document.getElementById("myDiv");

var event;
EventUtil.addHandler(div,"myevent",function(event){
  alert("DIV:   " + event.detail);
});
EventUtil.addHandler(document,"myevent",function(event){
  alert("DOCUMENT:   " + event.detail);
});

if(document.implementation.hasFeature("CustomEvents","3.0")){
  event = document.createEvent("CustomEvent");
  event.initCustomEvent("myevent",true,false,"hello world!");//對應參數:觸發事件類型、事件是否冒泡、事件是否能夠取消、任意值,保留在event對象的detail中
  div.dispatchEvent(event);
}

事件代理:

事件代理,具體實例,上邊的ul元素綁定index,能夠用。

相關文章
相關標籤/搜索