JavaScript Event學習第一章:Event介紹

來源:互聯網
上載者:User

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%的瀏覽器的不相容問題。只有滑鼠位置非常的麻煩,其他的都比較簡單了。
另外,最好根本就不要去想那三個事件模型。實際上,我們應該去理解四種事件註冊模型,兩種事件執行模型和兩種事件順序。 這裡可以快速查看下事件相容性列表。

現在聽起來好像非常的複雜,實際上並不是這樣。當我們注意到這個的時候也就應該開始真正的理解事件處理常式了。這都是關於如何提出正確的問題的。不要問“我該怎麼寫事件處理常式的代碼呢?”即使這是一個正確的問題,但是難以回答--那需要11頁長的文章才能說清楚。因此你應該問那些有具體答案的具體問題:

 “這裡都有什麼事件?”
“我怎麼對一個HTML元素註冊事件處理常式呢?”
“我怎麼阻止預設動作的發生呢?”
“當我想要得到更多的資訊的時候我怎麼訪問一個事件呢?”
“當我成功的觸發了事件,我怎麼讀取他的屬性呢?”

“如果一個元素和他的父元素對一個事件都有事件處理常式,那麼誰先執行呢?”

 上面所有的問題都會在單獨的章節進行詳細的解答。
寫跨瀏覽器的事件處理常式的的技巧在於不要用整體的事件模型而是分別的回答每一個問題。你會發現,你只有在需要讀出事件屬性的時候才需要考慮瀏覽器的相容性問題。

先選擇一個事件註冊模型,然後確定這個事件會在所有的瀏覽器裡面觸發,然後讀出正確的屬性,最後解決事件觸發順序問題-如果有的話。這樣你就能分貝的解決瀏覽器安全色性問題也能確保你的代碼能在所有的瀏覽器裡良好的運行。


繼續
如果你想按照順序學習事件,你應該開始讀下一章了。


寫事件處理常式的代碼
那麼怎樣寫事件處理常式的代碼呢?為了希望快速得到答案和打算以後再學習理論的童鞋,在這一章我會做一個簡單的概述。


註冊一個事件處理常式
第一步是先註冊你的事件處理常式。你需要確定的是瀏覽器會在任何時候都執行你的代碼。
這裡有四種註冊事件處理常式的方法:inline,traditional,w3c和Microsoft。
最好使用traditinal方法,因為他能很好的跨瀏覽器並且有很大的自由和通用性。註冊一個事件處理常式,如下:

element.onclick = doSomething;
if (element.captureEvents) element.captureEvents(Event.CLICK);

 現在這個函數doSomething()就註冊成為一個HTML的element元素click事件的事件處理常式。這意味著無論什麼時候使用者點擊了這個元素,那麼doSomething()都會執行。


訪問這個事件
但你註冊了你的事件處理常式你就開始寫真正的代碼了。通常你想訪問這個事件本身,所以你可以讀取這個事件的資訊。

訪問這個事件所以你可以讀出他的屬性,通常你的事件處理常式開始如下:

function doSomething(e) {
if (!e) var e = window.event
// e refers to the event
}

 
現在e就表示在所有瀏覽器裡面的事件,你也可以訪問這個事件。


訪問這個HTML元素
有時候你希望能夠訪問到發生事件的元素。這裡有兩個辦法:使用this關鍵字或者使用target/srcElement屬性。
比較保險的訪問HTML元素的方法是使用this關鍵字。this並不總是指向正確的HTML元素,但是和traditional模式一起就能很好的工作。


代碼
function doSomething(e) {
if (!e) var e = window.event
// e refers to the event
// this refers to the HTML element which currently handles the event
// target/srcElement refer to the HTML element the event originally took place on
}

 
target/srcElement屬性包含一個最初事件發生的HTML元素的引用。非常有用,但是當事件被捕獲或者冒泡了他依然是那個最初發生事件的元素不會改變。


讀取屬性
在讀出一些有趣的事件屬性(event properties)這個問題上,是瀏覽器安全色最不好的部分。學習這個相容性列表,然後寫出你自己的代碼來擷取你需要的資訊。
確定總是使用最仔細的對象檢查。首先確定每一個屬性是否存在,然後再讀取他的值。比如:

function doSomething(e) {
if (!e) var e = window.event
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
}
現在code就包括了所按下的鍵,並且相容所有的瀏覽器。


事件順序
最後,你需要決定你是否希望事件冒泡。如果不希望發生事件冒泡,那麼就阻止他:

function doSomething(e) {
if (!e) var e = window.event
// handle event
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}

 寫代碼
現在你可以開始寫事件處理常式的代碼了。通過前面的代碼和資訊,可以讓你知道事件什麼時候發生,你的代碼應該做怎樣的回應。記住:讓互動更有邏輯性要麼你的使用者不會理解發生了什麼。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.