JS事件

一、基本概念

1、事件冒泡
IE的事件流叫做事件冒泡,即事件開始時由最具體的元素接收,然後逐級向上傳播到較爲不具體的節點(文檔)。

2、事件捕獲
Netscape Communicator團隊提出的另一種事件流叫做事件捕獲。事件捕獲的思想是不太具體的節點應該更早接收到事件,而最具體的節點應該最後接收到事件。事件捕獲的用意在於在事件到達預定目標之前捕獲它。

3、DOM事件流
“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段、處於目標階段和事件冒泡階段。

二、事件處理程序

1、HTML事件處理程序

<input type="button" value="Click me" onclick="alert('Clicked')"/>

在HTML中定義的事件處理程序可以包含要執行的具體動作,也可以調用在頁面其他地方定義的腳本

<script type="text/javascript">
    function showMessage(){
        alert("Hello world");
    }
<script/>
<input type="button" value="Click Me" onclick="showMessage()"/>

事件處理程序中的代碼在執行時,有權訪問全局作用域中的任何代碼。

2、DOM0級事件處理程序
通過JavaScript指定事件處理程序的傳統方式,就是將一個函數賦值給一個事件處理程序。

var btn=document.getElementById("myBtn");
btn.onclick=function(){
    alert(this.id); //"myBtn"
};

btn.onclick=null; //刪除事件處理程序

這時候的事件處理程序是在元素的作用域中運行,所以會返回myBtn。

3、DOM2級事件處理程序
“DOM2級事件”定義了兩個方法,用於處理指定和刪除事件處理程序的操作:addEventListener()和removeEventListener()。
所有DOM節點中都包含這兩個方法,並且它們都接受3個參數:要處理的事件名、作爲事件處理程序的函數和一個布爾值。
最後這個布爾值參數如果是true,表示在捕獲階段調用事件處理程序;如果是false,表示在冒泡階段調用事件處理程序。

var btn=document.getElementById("mybtn");
btn.addEventListener("click",function(){
    alert(this.id);
 },false);
 btn.addEventListener("click",function(){
    alert("Hello world");
 },false);

這裏添加的事件處理程序也是在其依附的元素的作用域中運行。使用DOM2級方法添加事件處理程序的主要好處是可以添加多個事件處理程序。這兩個事件處理程序會按照添加它們的順序觸發。

通過addEventListener()添加的事件處理程序只能使用removeEventListener()來移除;移除時傳入的參數與添加處理程序時使用的參數相同。這也意味着通過addEventListener()添加的匿名函數將無法移除。

var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
    alert(this.id);
},false);
//這裏省略了其他代碼

btn.removeListener("click",function(){  //沒有用!
    alert(this.id);
},false);
var btn=document.getElementById("myBtn");
var handler=function(){
    alert(this.id);
};
btn.addEventListener("click",handler,false);
//這裏省略了其他代碼

btn.removeListener("click",handler,false); //有效

4、IE事件處理程序
attachEvent()和detachEvent(),只接受兩個參數。通過attachEvent()添加的事件處理程序都會被添加到冒泡階段。
在使用attachEvent()方法的情況下,事件處理程序會在全局作用域中運行,因此this等於window.

var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
    alert(this===window);    //true
});
var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
    alert("Clicked");    //該事件後觸發
});
btn.attachEvent("onclick",function(){
    alert("Hello world!");   //該事件先觸發
});

移除事件:

var btn=document.getElementById("myBtn");
var handler=function(){
    alert("Clicked");
};
btn.attachEvent("onclick",handler);
//這裏省略了其他代碼

btn.detachEvent("onclick",handler); 

5、跨瀏覽器的事件處理程序

var EventUtil={
 addHandler:function(element,type,handler){
    if(element.addEventListener){
     element.addEventListerner(type,handler,false);
     }else if(element.attachEvent){
         element.attachEvent("on"+type,handler);
     }else{
        element["on"+type]=handler;
    }
  },
 removerHandler:function(element,type,handler){
    if(element.removeEventListener){
     element.removeEventListener(type,handler,false);
   }else if(element.detachEvent){
    element.detachEvent("on"+type,handler);
   }else{
        element["on"+type]=null;
   }
 }
};

可以像下面這樣使用EventUtil對象:

var btn=document.getElementById("myBtn");
var handler=function(){
    alert("Clicked");
};

EventUtil.addHandler(btn,"click",handler);
//這裏省略了其他代碼
EventUtil.removeHandler(btn,"click",handler);

三、事件對象

1、DOM中的事件對象
兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中。無論指定事件處理程序時使用什麼方法(DOM0級或DOM2級),都會傳入event對象。

2、IE中的事件對象
與訪問DOM中的event對象不同,要訪問IE中的event對象有幾種不同的方式,取決於指定事件處理程序的方法。在使用DOM0級方法添加事件處理程序時,event對象作爲window對象的一個屬性存在。

3、跨瀏覽器的事件對象
IE中的event對象的全部信息和方法DOM對象中都有,只不過實現方式不一樣。

var EventUtil={
    addHandler:function(element,type,handler){
        //省略的代碼
    },
    getEvent:function(event){
        return event?event:window.event;
    },
    getTarget:function(event){
        return event.target||event.srcElement;
    },
    preventDefault:function(event){
        if(event.preventDefault){
            event.preventDefault();
         }else{
            event.returnValue=false;
        }
    },
    removeHandler:function(element,type,handler){
            //省略的代碼
        },
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation();
        }else{
            event.cancelBubble=true;
        }
    }
};

1、使用第一個方法:

btn.onclick=function(event){
 event=EventUtil.getEvent(event);
};

2、使用第二個方法:

btn.onclick=function(event){
 event=EventUtil.getEvent(event);
 var target=EventUtil.getTarget(event);
};

3、使用第三個方法:

var link=document.getElementById("myLink");
link.onclick=function(event){
 event=EventUtil.getEvent(event);
 EventUtil.preventDefault(event);
};

4、使用第四個方法:

var btn=document.getElementById("myBtn");
btn.onclick=function(event){
 alert("Clicked");
 event=EventUtil.getEvent(event);
 EventUtil.syopPropagation(event);
};

document.body.onclick=function(event){
    alert("Body clicked");
};

四、事件委託

對“事件處理程序過多”問題的解決方案就是事件委託。事件委託利用了事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。以下面的HTML代碼爲例:

<ul>
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</li>
</ul>

使用事件委託,只需要在DOM樹中儘量最高的層次上添加一個事件處理程序,如下面的例子所示:

var list=document.getElementById("myLinks");

EventUtil.addHandler(list,"click",function(event){
    event=EventUtil.getEvent(event);
    var target=EventUtil.getTarget(event);

    switch(target.id){
        case "doSomething":
        document.title="I changed the document's title";
        break;

        case "goSomewhere":
        location.href="http://www.wrox.com";
        break;

        case "sayHi":
        alert("hi");
        break;      
    }
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章