JS高級程序設計筆記——事件(一)

1、事件流

假設有以下HTML代碼:html

<!DOCTYPE html>
<html>
<head>
    <title>Event</title>
</head>
<body>
    <div id="myDiv">Click me</div>
</body>
</html>

其DOM樹以下圖所示:
圖片描述瀏覽器

若是點擊div元素,由於div是該DOM樹中層次最深的節點,那麼哪一個節點先接收事件?是由淺到深,仍是由深到淺?函數

事件流描述的是從頁面中接收事件的順序。
存在兩種事件流:事件冒泡(IE)和事件捕獲(Netscape)(這兩種事件流的事件傳播順序以下圖所示)
事件冒泡和事件捕獲this

DOM事件流

「DOM2級事件」規定的事件流包括三個階段:spa

  • 事件捕獲階段:首先發生,爲截獲事件提供了機會
  • 處於目標階段:實際的目標接收到事件
  • 事件冒泡階段:在此階段能夠對事件作出響應

仍以上面的例子爲例,單擊div元素的事件觸發順序以下圖所示:
DOM事件流code

2、事件處理程序

事件是用戶或瀏覽器自身執行的某種動做(好比click、load、mouseover等)
事件處理程序(事件偵聽器)是響應某個事件的函數。
事件處理程序的名字以「on」開頭,如click事件的事件處理程序是onclick。htm

爲事件指定處理程序的方式有如下幾種:對象

(一)HTML事件處理程序

可使用HTML爲元素指定事件處理程序,方法是:爲元素添加一個與事件處理程序同名的屬性,該屬性的值是可以執行的JS代碼或JS函數。blog

//直接定義JS代碼
<input type="button" value="點擊" onclick="alert('clicked')" />

//調用在頁面其餘地方定義的JS函數
<input type="button" value="點擊" onclick="showMessage()" />

以上代碼爲按鈕添加了鼠標單擊事件(click)的事件處理程序(onclick)。seo

:這樣定義的事件處理程序在執行時,有權訪問全局做用域中的任何代碼

(二)DOM0級事件處理程序

IE九、Firefox、Safari、Chrome和Opera支持DOM2級事件處理程序

一、定義事件處理程序

  • 使用JS代碼來給事件指定事件處理程序,方法是:將一個函數賦值給一個事件處理程序屬性
  • 每一個元素都有本身的事件處理程序屬性,這些屬性的名字與事件處理程序的名字相同,如onclick。
var btn = document.getElementById("myBtn");
//爲按鈕指定onclick事件處理程序
btn.onclick = function(){
    alert("Clicked");
}

注:

  • 使用DOM0級方法指定的事件處理程序被認爲是元素的方法(即事件處理程序是在元素的做用域中運行)
  • 以這種方式添加的事件處理程序會在事件流的冒泡階段被處理

二、刪除事件處理程序

將事件處理程序屬性的值設置爲null便可刪除事件處理程序:

btn.onclick = null;

(三)DOM2級事件處理程序

一、定義事件處理程序

「DOM2級事件」定義了兩個方法來處理事件處理程序:

  • addEventListener(要處理的事件名,事件處理程序函數,布爾值)

    • 布爾值取值爲false:在冒泡階段調用事件處理程序
    • 布爾值取值爲true:在捕獲階段調用事件處理程序
  • removeEventListener(要處理的事件名,事件處理程序函數,布爾值)
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
    alert(this.id);
}, false);

注:

  • 大多數都是將事件處理程序添加到冒泡階段,從而保證跨瀏覽器的兼容性,故一般都是將最後一個參數設爲false
  • 全部的DOM節點都包含上述兩個方法
  • DOM2級添加的事件處理程序也是在其依附的元素的做用域中運行的
  • 使用DOM2級方法能夠爲同一個元素添加多個事件處理程序,這些事件處理程序會按照添加它們的順序從上到下執行(DOM0級只能爲同一個元素添加一個事件處理程序)

二、刪除事件處理程序

經過addEventListener()添加的事件處理程序只能經過removeEventListener()刪除,且刪除時傳入的參數必須與添加時傳入的參數相同。
可是經過addEventListener()添加的匿名函數沒法移除,最好是在其餘地方定義事件處理程序的函數,而後將該函數的名稱傳給第二個參數。

var btn = document.getElementById("myBtn");

//定義事件處理程序函數
var handler = function(){
    alert(this.id);
}

btn.addEventListener("click", handler, false);

btn.removeEventListener("click", handler, false);

(四)IE事件處理程序

支持IE事件處理程序的瀏覽器有IE和Opera

IE定義了兩個與DOM2級相似的方法:

  • attachEvent(事件處理程序名稱,事件處理程序函數):經過方法添加的事件處理程序會被添加到冒泡階段
  • detachEvent(事件處理程序名稱,事件處理程序函數)
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
    alert(this.id);
});

注:

  • 使用attachEvent()方法時,事件處理程序會在全局做用域中運行(與DOM方法不一樣)
  • attachEvent()一樣能夠爲同一個元素添加多個事件處理程序,但這些事件處理程序是以定義的相反方向執行的
  • detachEvent()刪除事件處理程序時,需傳入與attachEvent()相同的參數,且沒法刪除匿名函數。

(五)跨瀏覽器的事件處理程序

爲了保證跨瀏覽器的兼容性,咱們定義一個EventUtil對象,它包含addHandler()和removeHandler()兩個方法。

var EventUtil = {
    //addHandler()方法
    addHandler:function(element, type, handler){
        //DOM2級事件處理程序
        if(element.addEventListener){
            element.addEventListener(type, handler, false);
        }
        //IE事件處理程序
        else if(element.attachEvent){
            element.attachEvent("on"+type, handler);
        }
        //默認使用DOM0級事件處理程序
        else{
            element["on"+type]=handler;
        }
    },
    //removeHandler()方法
    removeHandler: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]=handler;
        }
    }
};

3、事件對象

觸發DOM上的某個事件時,會產生一個event事件對象,該對象包含着全部與事件有關的信息。
全部瀏覽器都支持event對象,但支持的方式不一樣。

(一)DOM中的事件對象

一、event對象

兼容DOM(DOM0級和DOM2級)的瀏覽器將event對象傳入到事件處理程序中。

var btn = document.getElementById("myBtn");
btn.onclick = function(event){
    alert(event.type);  //"click"
};
btn.addEventListener("click", function(event){
    alert(event.type);  //"click"
}, false);

二、event對象的屬性和方法

event對象的屬性和方法以下圖所示:
event對象的屬性和方法

在上圖中,currentTarget的值始終等於this,而target只包含事件的實際目標。

  • 若是直接將事件處理程序指定給了目標元素,則this === currentTarget === target

    var btn = document.getElementById("myBtn");
    btn.onclick = function(event){
        alert(event.currentTarget === this);  //true
        alert(event.target === this);  //true 
    }
    
    //上例中,點擊事件的目標是按鈕,而且把事件處理程序直接給了目標元素,因此三者的值相等
  • 若是將事件處理程序沒有直接指定給目標元素,this === currentTarget !== target

    document.body.onclick = function(event){
        alert(event.currentTarget === document.body);  //true
        alert(this === document.body);  //true
        alert(target === document.getElementById("myBtn"));  //true
    }
    
    //上例中,點擊世界的目標是按鈕,可是事件處理程序制定給了body元素,故三者並不相等。

(二)IE中的事件對象

一、訪問event對象

在IE中,指定事件處理程序的方法不一樣,訪問event對象的方法也不一樣:

(1)使用DOM0級添加事件處理程序 —— event對象是window對象的一個屬性

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    var event = window.event;
    alert(event.type);  //"click"
}

(2)使用attachEvent()添加事件處理程序 —— event對象會被傳入事件處理程序函數中

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(event){
    alert(event.type);  //"click"
});

(3)經過HTML特性指定事件處理程序 —— 經過event變量來訪問event對象

<input type="button" vaule="Click me" onclick="alert(event.type)"/>

二、IE 中event對象的屬性和方法

IE event屬性和方法

(三)跨瀏覽器的事件對象

雖然DOM和IE中的event對象不一樣,但基於它們之間的類似性,能夠實現跨瀏覽器的兼容性

var EventUntil = {
    
    //省略代碼
    addHandler: function(element, type, handler){},
    
    //獲取event對象
    getEvent: function(event){
        return event ? event : window.event;  
    },
    
    //獲取target
    getTarget: function(event){
        return event.target||event.srcElement;
    },
    
    //取消事件的默認行爲
    preventDefault: function(event){
        if(event.preventDefault){
            event.preventDefault();
        }
        else{
            event.returnValue = false;
        }
    },
    
    //取消冒泡
    stopPropagation: function(event){
        if(event.stopPropagation){
            event.stopPropagation();
        }
        else{
            event.cancelBubble = true;
        }
    },
    
    //省略代碼
    removeHandler:function(element, type, handler){}
};
相關文章
相關標籤/搜索