Events是每一個JavaScript程序核心。什么是事件處理,它有什么問題和怎樣寫出跨瀏覽器的代碼,我將在這一章做一個概述。我也會提供一些有精彩的關于事件處理程序的細節的文章。
沒有event就沒有腳本。可以看看任何有JavaScript代碼的網頁:幾乎所有的例子都有一個事件觸發了腳本。原因非常簡單。JavaScript就是給你的頁面添加內部活動:用戶做一些事情然后頁面做出回應。
因此JavaScript就需要一個方法能夠檢測到用戶的動作然后才能知道什么時候做出反應。這還需要知道那個函數會被執行,函數會做一些你認為的給你的網頁增色的動作。這些文字描述了如何去寫這樣的腳本。雖然不容易,但是這是一個很讓人滿足的工作。
當用戶做了什么事情event就發生了,當然還有一些event不會直接被用戶觸發:比如load事件會在頁面裝載完畢的時候觸發。
JavaScript能夠檢測一些event。從Netscape 2開始,在HTML元素上添加event hanlder就成為可能。這些事件處理函數等待一個確定的事件,比如點擊一個鏈接。當他發生的時候,事件就會通過你指定的JavaScript代碼來執行。
當用戶做出動作他就引發了一個事件。當你的代碼讓頁面對這個動作做出回應,交互就產生了。
事件處理程序的歷史
如上所述,沒有事件處理程序就沒有在頁面添加JavaScript的必要。那些能對用戶動作做出反應的就是最好的腳本。因此,當Netscape發布他的第二版支持JavaScript的瀏覽器的時候,他同時也支持event。
Netscape模式
Netscape只支持一小部分事件。Mouseover和mouseout的快速流行時因為當鼠標滑入時改變圖片而滑出時又返回到原來的狀態這個很炫的效果。而且可以看到用戶是否提交了表單或者重置了表單,這樣在客戶端的驗證也就成為了可能。瀏覽器還能監測表單的某一項獲得或者失去了焦點或者頁面完成下載又或者開始關閉。在如今看來這些都是非常稀松平常的事情,但在那個時候那可是革命性的。因為你能對用戶的動作做出反饋,所以真正的交互才變成可能。
在最古老的表單的事件處理程序看起來是這樣的。當用戶點擊了鏈接,事件處理程序就被執行了然后彈出對話框。
<a href="somewhere.html" onclick="alert('I've been clicked!')">
注意到這種最古老的處理事件的方法事實上就是Netscape的標準是很重要的。如果想要JavaScript工作,其他的瀏覽器包括IE都得遵從Netscape 2和3的處理事件的標準。因此這些最古老的事件和事件處理程序在任何JavaScript瀏覽器中都能很好的運行。
現在的事件模式
然而,相比之前的介紹,現在的事件處理程序有了很大的變化。第一就是數量上急劇增長。對HTML元素的事件處理程序的注冊的方法也有很大的變化。現在完全可由JavaScript設置。不再需要大量的附著于代碼之上,你可以寫一些很簡單的代碼來設置所有的事件處理程序。
V4瀏覽器也提供了關于事件的很多信息。鼠標在哪?什么時候事件發生?鍵盤按下了么?最終,瀏覽器必須要對一個元素和這個元素的父元素對同一個動作都有事件處理程序做出選擇。哪個事件先觸發呢?
因為這個功能而更加加劇了瀏覽器之間的戰火,Netscape和微軟制訂了幾乎互不兼容的兩套事件模型。最近第三種模型開始顯現,這是由w3c發布的DOM Event specification 。雖然有一個嚴重的缺陷,w3c模型是基于舊的Netscape模型但是更加的廣義和通用,這是一份非常杰出的作品,添加了很多有趣的函數,也解決了一些老的事件模型存在的問題。
既然存在三種模型,所以事件處理程序也就不能以同樣的方式在所有的瀏覽器里面運行。
瀏覽器的兼容性問題
我們繼續。就像DHTML,w3c DOM或者其他高級的腳本技術一樣,我們對于代買的每一個字節都要小心。在IE中使用stopPropagation()或者在Netscape中使用srcElement都會導致嚴重的錯誤而使我們的代碼毫無用處。因此在使用方法或者屬性之前我們必須對瀏覽器的支持性做必要的檢查。
一個簡單的代碼片段如下:
if (Netscape) {
use Netscape model
}
else if (Explorer) {
use Microsoft model
}
這只是解決問題的一個開始而已。最近的瀏覽器能運行的事件處理程序的數量是巨大的,除非你的代碼不允許除了Netscape或者IE其他少數瀏覽器運行。
所有的小眾瀏覽器都必須不那么光彩的決定支持那種事件模型。Konqueror/Safari通常都選擇嚴格的按照W3C的標準執行。Opera和iCab通常都會支持大部分的老的Netscape模型和一些微軟的模型。我對其他的更小眾的瀏覽器還沒有做研究。
但是其他的更小眾的瀏覽器可能選擇支持微軟處理事件的方法,同時又有W3C和老的Netscape的屬性。這都沒什么問題,總之他們都是以他們自己的方法支持我們知道的模型。你的代碼應該沒有問題。
不要使用瀏覽器類型檢測
首先,永遠永遠都不要使用瀏覽器檢測,這是通向地獄的捷徑。任何代碼如果使用navigator.userAgent來做事件模型的檢測,那簡直比沒用還沒用應該直接拉出去彈JJ。
第二,不要被DHTML的object detection的事件對象檢測所迷惑。當你寫DHTML的時候通常檢測DOM的支持性,比如,if(document.all)。如果支持,那么代碼如果使用Microsot的all容器就能搞很好的運行。
但是DHTML和事件處理程序有不同的瀏覽器兼容性模式。比如,Opera 6支持W3C DOM的一部分但是不支持W3C event模型。因此DHTML對象檢測在Opera下會做出錯誤的決定。所以代碼使用if(document.layers)或者其他的事件模型檢測都是不正確的。
正確的問題
那么我們怎么辦?Event屬性的名字造成了這些問題。如果我們針對具體的對象探測使用不同的辦法,基本上能解決99%的瀏覽器的不兼容問題。只有鼠標位置非常的麻煩,其他的都比較簡單了。
另外,最好根本就不要去想那三個事件模型。實際上,我們應該去理解四種事件注冊模型,兩種事件執行模型和兩種事件順序。 這里可以快速查看下事件兼容性列表。
下一篇 寫HTML和CSS的新方法