200907052358淺談 JavaScript 的 DOM Event 註冊方式

大致來說 DOM Event 註冊方式可以分為三種,傳統式、 W3C DOM 標準式、 IE 式。這篇文章簡單介紹這三種註冊方式,介紹的範例共用以下程式碼:

<div id="div1"> 
  <a id="link" href="http://xuite.net/" >Link</a> 
</div> 
<script> 
  var oLink = document.getElementById('link'); 
 
  function handler() { 
    alert(this.nodeName); 
  } 
</script>

 

傳統式

顧名思義是最早的註冊方式,所有的瀏覽器都支援。註冊方法如下︰

oLink.onclick = handler;

取消註冊︰

oLink.onclick = null;

點下 oLink , alert(this.nodeName) 會跳 A ,因為 this 是 oLink 。

將 DOM Event inline 寫在 HTML 中,也算傳統式的一種。 <a onclick="..." > ,雙引號中的內容就等於寫在 handler 裡。以上面的範例來看 oLink.onclick = handler 相當於 <a onclick="alert(this.nodeName)" > 。

傳統式的問題是當我要在 onclick 上註冊兩個 function 時,就沒轍了。也許我可以動點手腳,變成這樣:

function handler() { 
  func1(); 
  func2(); 
}

但要將其中一個函式取消註冊時呢?

 

W3C DOM 標準式

因為傳統式多重註冊的問題,才有後來的 W3C DOM 標準式和 IE 式。 IE 以外的瀏覽器都支援 W3C DOM 標準式, IE 則從第九版才開始支援。註冊方法如下︰

oLink.addEventListener('click', handler, false);

取消註冊︰

oLink.removeEventListener('click', handler, false);

傳統式多重註冊的問題解決了,要註冊多個函式或移除其中一個函式皆沒有問題。點下 oLink , alert(this.nodeName) 會跳 A ,因為 this 是 oLink 。

addEventListener 和 removeEventListener 傳入的第三個參數叫 useCapture ,和整個網頁中的 Event 執行次序有關。以這篇文章所有範例共用的程式碼來看, <div> 包住 <a> ,如果 <div> 和 <a> 都有註冊 click event ,<div> 和 <a> 誰的 click event 應該先被執行?

依照 W3C DOM 標準, Event 的傳遞分成兩階段,第一階段是由上到下,叫 Capture ;第二階段是由下到上,叫 Bubble 。以剛剛 <div> 和 <a> 的例子,第一階段 Capture 由上到下就是由 <div> 到 <a> ;第二階段 Bubble 由下到上就是由 <a> 到 <div> ,所以整個 Event 的傳遞順序就是 <div> → <a> → <a> → <div> 。

addEventListener 第三個參數就是在決定函式要在 Capture 的階段執行,還是 Bubble 的階段執行。 true → Capture 階段, false → Bubble 階段。 removeEventListener 第三個參數則是用來指明要取消註冊的是 Capture 階段的函式,還是 Bubble 階段的函式。

補充 W3C 官方文件有圖片說明,也許會比較好理解。

但是 addEventListener 和 removeEventListener 的第三個參數 useCapture 多半傳入 false ,因為傳統式和 IE 式皆不支援 Capture 階段執行函式,為了跨瀏覽器相容,只好忍痛放棄 Capture 階段執行函式。

 

IE 式

顧名思義,只有 IE 支援,註冊方式如下:

oLink.attachEvent('onclick', handler);

取消註冊:

oLink.detachEvent('onclick', handler);

點下 oLink , alert(this.nodeName) 會跳 undefined ,因為 IE 式 this 是 window 。這是 IE 式最大的問題。

 

總結

整個看下來會發現所有瀏覽器都支援的是傳統式,功能最完整的是 W3C DOM 標準式。可是傳統式無法多重註冊的問題實在太明顯,因此 2005 年 ppk 舉辦了一場比賽,尋求跨瀏覽器解決傳統式無法多重註冊的方法。最後由 Dean Edwards 勝出:

現在各 JavaScript Library 所採用的方法,多半是 Dean Edwards 解法的延伸。但隨著 W3C DOM 標準式逐漸成為新瀏覽器的主流,多會先判斷是否支援 W3C DOM 標準式,支援就採用,將 Dean Edwards 的解法當備援,不支援 W3C DOM 標準式才使用。

延伸 無作用連結的 href 該寫 # 還是 javascript: void(0)
回應
Google 站內搜尋
BloggerAds
累積 | 今日
loading......
    沒有新回應!





Powered by Xuite