《JavaScript高級程序設計》學習筆記:JavaScript中的事件流和事件處理程序

JavaScript和HTML之間的交互是經過事件實現的。javascript

事件:文檔或瀏覽器窗口中發生的一些特定的交互瞬間。java

能夠使用偵聽器(或處理程序來預訂事件),以便事件發生時執行相應的代碼。瀏覽器


1. 事件流

事件流:從頁面中接收事件的順序。函數

IE和Netscape開發團隊提出了差很少是徹底相反的事件流的概念。this

  • IE: 事件冒泡流
  • Netscape: 事件捕獲流

1.1 事件冒泡

事件冒泡(event bubbling):事件開始時由最具體的元素(文檔中嵌套層次最深的那個節點)接收,而後逐級向上傳播到較爲不具體的節點(文檔)。code

1.2 事件捕獲

事件捕獲(event capturing):不太具體的節點應該更早接收到事件,最具體的節點應該最後接收到事件。對象

事件捕獲的用意在於在事件到達預約目標以前捕獲它。seo

1.3 DOM事件流

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

1. 事件捕獲階段
2. 處於目標階段
3. 事件冒泡階段

2. 事件處理程序

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

2.1 HTML事件處理程序

某個元素支持的每種事件,均可以使用一個與相應事件處理程序同名的HTML特性來指定。

<input type="button" value="Clicke Me" onclick="alert('Clicked')" />

單擊按鈕,顯示警告框。經過指定 onclick 特性並將一些JavaScript代碼做爲它的值來定義。

在HTML中定義的事件處理程序能夠包含要執行的具體動做,也能夠調用在頁面其餘地方定義的腳本。

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

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

缺點:

  1. 存在時差問題。用戶在事件處理程序被解析以前就觸發了事件。
  2. 擴展事件處理程序的做用域鏈在不一樣的瀏覽器中會致使不一樣結果。
  3. HTML和JavaScript代碼緊密耦合。

2.2 DOM0 級事件處理程序

經過JavaScript指定事件處理程序的傳統方式,就是將一個函數賦值給一個事件處理程序屬性。

這種方法被稱爲事件處理程序賦值,出如今第四代 Web 瀏覽器中。

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

<input type="button" id="myBtn" value="Click Me" />
    
    <script type="text/javascript">
        var btn = document.getElementById("myBtn");
        btn.onclick = function() {
            alert("Clicked");
        }
    </script>

能夠刪除經過 DOM0 級方法指定的事件處理程序。

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

2.3 DOM2 級事件處理程序

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

  • addEventListener()
  • removeEventListener()

全部 DOM 節點都包含這兩個方法,它們接受3個參數:

  1. 要處理的事件名
  2. 做爲事件處理程序的函數
  3. 一個布爾值:

    • true: 捕獲階段調用事件處理程序
    • false: 冒泡階段調用

爲一個按鈕添加 onclick 事件處理程序:

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

使用 DOM2級方法添加事件處理程序的主要好處是能夠添加多個事件處理程序。

用 addEventListener() 添加的事件處理程序只能使用 removeEventListener() 來移除,移除時傳入的參數與添加時的參數相同。因此,用 addEventListener() 添加的匿名函數將沒法移除。

大多數狀況下,都是將事件處理程序添加到事件流的冒泡階段,這樣能夠最大限度地兼容各類瀏覽器。

2.4 IE 事件處理程序

IE 實現了與 DOM 中相似的兩個方法:

  • attachEvent()
  • detachEvent()

接受兩個參數:事件處理程序名稱、事件處理程序函數
經過這種方法添加的事件處理程序會被添加到冒泡階段。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
    alert("clicked");
});

注意: attachEvent() 的第一個參數是「onclick」,而不是 addEventListener()方法中的「click"。

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

  • DOM0 級方法:事件處理程序會在其所屬元素的做用域內運行
  • attachEvent()方法:事件處理程序會在全局做用域內運行,this 等於 window。

2.5 跨瀏覽器的事件處理程序

建立一個方法 addHandler(),它屬於名叫EventUtil的對象視狀況分別使用 DOM0級方法、 DOM2級方法或IE方法來添加事件。

addHandler()方法接收3個參數:

  1. 要操做的元素
  2. 事件名稱
  3. 事件處理程序函數

與其對應的方法是 removeHandler(),接收相同的參數。

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

    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] = null;
        }
    }
}

這兩個方法首先都會檢測傳入的元素中是否存在DOM2級方法。若是存在DOM2級方法,則使用該方法。若是存在的是IE的方法,則採起第二種方案。

像下面這樣使用EventUtil對象:

var btn = document.getElementById("myBtn");
var handler = function() {
    alert("Clicked");
}
EventUtil.addHandler(btn, "click", handler);
EventUtil.removerHandler(btn, "click", handler);
相關文章
相關標籤/搜索