JavaScript事件流

 

1.概述html

事件流:頁面中接受事件的順序。瀏覽器

IE的事件流是事件冒泡流,而Netscape的事件流是事件捕獲流。函數

 

二、事件冒泡this

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

也就是說, click 事件首先在 <div> 元素上發生,而這個元素就是咱們單擊的元素。而後, click事件沿 DOM 樹向上傳播,在每一級節點上都會發生,直至傳播到 document 對象。code

全部現代瀏覽器都支持事件冒泡,但在具體實現上仍是有一些差異。IE5.5 及更早版本中的事件冒泡會跳過 <html> 元素(從 <body> 直接跳到 document )。IE九、Firefox、Chrome 和 Safari 則將事件一直冒泡到 window 對象htm

三、事件捕獲對象

  事件捕獲的思想是不太具體的節點應該更早接收到事件,而最具體的節點最後接收到事件。blog

雖然事件捕獲是 Netscape Communicator 惟一支持的事件流模型,但 IE九、Safari、Chrome、Opera和 Firefox 目前也都支持這種事件流模型事件

儘管「DOM2 級事件」規範要求事件應該從 document 對象開始傳播,但這些瀏覽器都是從 window 對象開始捕獲事件的

IE九、Opera、Firefox、Chrome 和 Safari 都支持 DOM 事件流;IE8 及更早版本不支持 DOM 事件流

四、事件處理程序

(1)HTML事件處理程序

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

缺點:

 HTML 與 JavaScript 代碼緊密耦合

(2)DOM0級事件處理程序

var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert("Clicked"); };
btn.onclick = null; //刪除事件處理程序

 

優勢:跨瀏覽器的優點,全部現代瀏覽器所支。缺點:DOM0 級對每一個事件只支持一個事件處理程序。

 


(3)DOM2級事件處理程序

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

全部 DOM 節點中都包含這兩個方法,而且它們都接受 3 個參數:要處理的事件名、做爲事件處理程序的函數和一個布爾值。最後這個布爾值參數若是是 true ,表示在捕獲階段調用事件處理程序;若是是 false ,表示在冒泡階段調用事件處理程序注意添加的事件相似爲click,非onclick

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

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

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

這裏爲按鈕添加了兩個事件處理程序。這兩個事件處理程序會按照添加它們的順序觸發,所以首先會顯示元素的 ID,其次會顯示 "Hello world!" 消息。

經過 addEventListener() 添加的事件處理程序只能使用 removeEventListener() 來移除;移除時傳入的參數與添加處理程序時使用的參數相同。

這也意味着經過 addEventListener() 添加的匿名函數將沒法移除

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

以上代碼不行。應該修改成:

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

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

(4)IE事件處理程序

IE 實現了與 DOM 中相似的兩個方法: attachEvent() 和 detachEvent() 。這兩個方法接受相同的兩個參數:事件處理程序名稱與事件處理程序函數。因爲 IE8 及更早版本只支持事件冒泡,因此經過attachEvent() 添加的事件處理程序都會被添加到冒泡階段。

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

注意, attachEvent() 的第一個參數是 "onclick" ,而非 DOM 的 addEventListener() 方法中的 "click"

在 IE 中使用 attachEvent() 與使用 DOM0 級方法的主要區別在於事件處理程序的做用域。在使用 DOM0 級方法的狀況下,事件處理程序會在其所屬元素的做用域內運行;在使用 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!"); });

這裏調用了兩次 attachEvent() ,爲同一個按鈕添加了兩個不一樣的事件處理程序。不過,與 DOM方法不一樣的是,這些事件處理程序不是以添加它們的順序執行,而是以相反的順序被觸發。單擊這個例子中的按鈕,首先看到的是 "Hello world!" ,而後纔是 "Clicked" 。

使用 attachEvent() 添加的事件能夠經過 detachEvent() 來移除,條件是必須提供相同的參數。與 DOM 方法同樣,這也意味着添加的匿名函數將不能被移除

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

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

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; } } };

addHandler() 和 removeHandler() 沒有考慮到全部的瀏覽器問題,例如在 IE 中的做用域問題

此外還要注意,DOM0 級對每一個事件只支持一個事件處理程序

 

六、更新2019.1.3 

還有DOM3事件流。DOM3事件流添加了更多的方法。如keydown等。

相關文章
相關標籤/搜索