原文並非是是三部曲,而是一系列講解javascript基礎的文章。我是把其中三篇抽出來,作為一個整體,對理解事件綁定模型相當有協助,原文在這裡http://www.quirksmode.org/js/events_early.html
今天我會解釋最早期的添加事件處理函數的方法,這種方式甚至在第二代瀏覽器(Version2 Browers)中也得到支援
早期的瀏覽器只支援一種函數綁定方式,由Netscape發明的。並且至今還不存在任何的相容性問題,由於當時Netscape的龍頭地位,微軟如果也想創造一款能運行javascript的瀏覽器,它就必須服從Netscape的指定標準。所以這種模式在所有javascript瀏覽器中都行得通——除了Mac上的IE3,它壓根對javascript中的”事件”不支援
綁定事件處理函數
在行內事件綁定模型(inline event registration model)中,處理函數作為它們服務的html元素的一個屬性被添加,就像
<A HREF="somewhere.html" onClick="alert('I\'ve been clicked!')">
當在這個超連結上有點擊事件發生時,處理函數被調用並且執行這段指令碼:一個彈出框出現了。你也可以調用一個javascript函數:
<A HREF="somewhere.html" onClick="doSomething()">
對於事件名稱中的大小寫混合(如onClick,onMouseOver)只是習慣問題,HTML對大小寫並沒有嚴格規定,所以你想大小寫都行。但是在XHTML中所有屬性名稱都必須小寫,所以如果你使用的是XHMTL你必須寫如成onclick和onmouseover
別使用它
儘管行內事件綁定模型有相當長一段時間並且非常可靠,它也有一個嚴重的缺陷,它要求javascript指令碼被寫入XHTML的結構層(於html標籤混在一起),但是它並不應該在那。
所以我強烈建議你並不應該使用這種模型,請看我這篇文章《談指令碼與結構層的分離》,裡面進行了全面的討論
預設行為(Default Action)
在那之後不久Netscape開始打html元素預設行為(如超連結預設行為是跳轉頁面)的主意,如考慮如何阻止預設行為發生。要補充的是,它的這個模型還是在瀏覽器大戰中生存了下來,並且被標準化,所以至今它仍然能工作良好。
和我們所知道的一樣,當使用者點擊一個超連結,瀏覽器根據它的href屬性跳轉到指定的頁面。這就是所謂的超連結點擊事件的預設行為。但是如果你同時也給這個連結的點擊事件綁定了一個onclick處理函數該怎麼辦?它會被執行嗎,在什麼時候?
<A HREF="somewhere.html" onClick="doSomething()">
在這個超連結中存在單擊處理函數的例子中,處理函數必須想方設法首先被執行。因為一旦預設行為發生,新頁面被載入,在瀏覽器記憶體中的舊頁面和它的那些處理函數會被統統抹去。所以如果想讓單擊處理函數被執行,它必須先於預設行為。
這被視為函數綁定的重要原則,如果事件同時引起預設行為發生和處理函數的執行:
- 處理函數首先被執行
- 預設行為才能隨後發生
所以在我們之前的例子中doSomething()會被首先執行,在那之後瀏覽器才會根據連結跳轉頁面。
阻止預設行為
當上面那些原則被確定之後,人們又開始考慮是否要阻止預設行為發生。在之前例子中,阻止瀏覽器根據連結跳轉頁面是可能的
因此規定根據事件處理函數的返回布爾值(true or false)判斷是否阻止。當返回false時,就意味著“不發生預設行為”,如果我們把我們的例子改為:
<A HREF="somewhere.html" onClick="doSomething(); return false">
則超連結永遠也不會起作用。函數被執行並且返回一個false,告訴瀏覽器別執行預設行為
當然也可以讓函數來決定是否執行預設行為,把例子改為:
<A HREF="somewhere.html" onClick="return doSomething()">
function doSomething()
{
return confirm('Do you really want to follow this link?')
}
這是非常簡單使用者互動,使用者被問到這個問題。如果他的答案是”OK”,函數返回true。如果他選擇”Cancel”,則返回false。這個結果被捕獲,被返回給事件自己,如果結果是false,則預設行為被取消,超連結不起作用
但無論如果,你無法阻止所有的預設行為發生,如unload就不可以被阻止。設想使用者正在關閉瀏覽器視窗——觸發了這個視窗中頁面的unload事件,如果你可以阻止這種unload,那就意味著無視使用者的意願而讓視窗仍然開啟?門都沒有
你當然可以嘗試阻止unload,通過使用微軟的beforeunload事件屬性。但是想象一下,當使用者被想關閉視窗時,還要被詢問是否確定,會讓他感到一點奇怪吧。所以最好別用它。
用返回false來阻止預設行為的發生,在所有瀏覽器中都是有效,它是事件處理函數最基本的一部分。現代的事件處理模型以及添加了阻止預設行為的新方法:
- W3C給事件添加了preventDefault()方法,如果你調用它預設行為被阻止
- 微軟給事件添加了returnValue屬性,如果設為false,預設行為被阻止
但是你不需要用上他們,一個簡單的return fasle就足夠了
window.status
return false中有一個例外,當使用者把滑鼠移上一個超連結時,你同時想改變狀態列的文字,這也是一種阻止預設行為——阻止狀態列顯示href的連結地址。在這種情況下必須返回true
<A HREF="somewhere.html"
onMouseOver="window.status = 'This link goes somewhere'; return true">
如果你不這麼做,代碼便不會工作。沒有人知道這是為什麼,就當它是許許多多奇怪的事情之一。
this關鍵字
在javascript中this關鍵字代表擁有它的函數。在事件處理函數中,this是對正在處理事件html元素的引用,這一點非常有用,它可以根據這一點訪問它。
不幸的是,雖然this關鍵字非常有用,但是如果你不是非常清楚它如何工作的話,它也非常難使用。我在另一篇文章有談論。在這我把它在行內模型中的使用作一個簡短的小結:
<A HREF="somewhere.html" onClick="doSomething(this)">
function doSomething(obj)
{
// obj now refers to the link
}
你把一個對超連結的引用,也就是儲存在obj中,傳遞給函數。現在你不需要為了找使用者正在點擊元素,而搜尋整個頁面:它被安全的存貯在obj中,現在可以這麼做:
<A HREF="somewhere.html" onClick="return doSomething(this)">
<A HREF="somewhereElse.html" onClick="return doSomething(this)">
function doSomething(obj)
{
var linkTo = obj.href;
return confirm('Do you really want to follow the link to ' + linkTo + '?')
}
這個函數接收到一個變數obj,它是對超連結的引用。你可以訪問它的href屬性,並且把它用在confirm對話方塊中。這麼做技巧在於你可以把這個處理函數添加到頁面中的任何超連結中,:它總是能正確的提示現在正在被點擊的超連結
繼續
下一篇將介紹傳統事件綁定模型(Traditional event registration model)