基本事件模型



網頁應用程式本身就是事件驅動,透過使用者的操作或系統的事件,在適當的時候作些事情。在事件標準化之前,就存在於各瀏覽器的一個事件模型,稱為基本事件模型(Basic Event Model),雖然沒有標準化,但因相對(於DOM Level 2事件與Internet Explorer事件模型)來說,有比較跨瀏覽器的一致性,因此是大多數人最熟悉且最常用的事件模型。

在基本事件模型中,要在某個事件發生時,呼叫指定的函式,是將函式指定給某個特性。例如,要在網頁文件準備好,所有資源都載入後作些事情,可以註冊window的load事件,方式就是將函式指定給window.onload特性,這是至今的範例都看到的:
window.onload = function() {
    // onload 事件發生時要作的事...
};

例如,要在按鈕的click事件發生時作些事,可以指定函式給按鈕元素的onclick特性。
<html>
<head>
<title>BasicEventModel-1</title>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
function handler() {
document.getElementById('console').innerHTML
= 'Who\'s clicked: ' + this.id;
}
document.getElementById('btn1').onclick = handler;
document.getElementById('btn2').onclick = handler;
};
</script>
</head>
<body>
<button id="btn1">按鈕一</button><br>
<button id="btn2">按鈕二</button><br>
<div id="console"></div>
</body>
</html>

在上例中,用handler()函式註冊了兩個按鈕的click事件,事件在元素上觸發而呼叫函式時,this就會設定為當時觸發事件的元素。在這個例子中,當你按下按鈕時而呼叫函式時,this就參考至當時按下的按鈕。像以上的作法,稱之為傳統模型(Traditional model)或傳統註冊模型(Traditional registration model)。

儘管現在已不建議接下來的作法,但在過去開發的網頁程式中經常看到的作法就是,在標籤的屬性上撰寫
JavaScript作為觸發事件時要執行的程式,這樣的作法稱之為行內模型(Inline model)或行內註冊模型(Inline registration model)。例如:
<html>
<head>
<title>BasicEventModel-2</title>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<script type="text/javascript">
function handle(element) {
document.getElementById('console').innerHTML
= 'Who\'s clicked: ' + element.id;
}
</script>
</head>
<body>
<button id="btn1" onclick="handle(this);">按鈕一</button><br>
<button id="btn2" onclick="handle(this);">按鈕二</button><br>
<div id="console"></div>
</body>
</html>

在標籤屬性上撰寫程式碼,儘管只有一小段,但仍算是在畫面中侵入程式碼,現在已不鼓勵這樣的作法。在上例中,並非直接指定click事件的處理器函式,事實上,在標籤上指定程式碼的作法,會自動建立匿名函式,也就是說,上例相當於:
document.getElementById('btn1').onclick = function() {
    handle(this);
};

你指定的程式碼,會成為匿名函式的本體內容,這也說明了上例中,this其實就是指觸發事件時的元素。

有些事件觸發時會有預設的動作,例如表單的submit事件預設會發送表單,超鏈結的click事件預設會連結至指定網頁。在基本事件模型中,若要取消預設事件動作,可以讓事件處理器傳回false。例如:
<html>
<head>
<title>BasicEventModel-3</title>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<script type="text/javascript">
window.onload = function() {
document.form1.onsubmit = function() {
if(this.data.value.length === 0) {
return false;
}
};
};
</script>
</head>
<body>
<form name="form1" action="fake.do">
輸入資料:<input name="data"><br>
<button type="submit">送出</button>
</form>
</body>
</html>

在上例中,按下按鈕會觸發表單的submit事件,你檢查欄位是否有填值,沒有的話就在事件處理器中傳回false,這會取消表單的發送,而這就是表單驗證的基本作法。若是使用行內模型。就會看到這種作法:
<html>
<head>
<title>BasicEventModel-4</title>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<script type="text/javascript">
function validate(form) {
if(form.data.value.length === 0) {
return false;
}
return true;
}
</script>
</head>
<body>
<form name="form1" action="fake.do"
onsubmit="return validate(this);">
輸入資料:<input name="data"><br>
<button type="submit">送出</button>
</form>
</body>
</html>

要在使用者離開頁面時,作一個簡單的確認,若使用行內模型,可以如下:
<a href="http://caterpillar.onlyfun.net"
   onclick="return confirm('要離開了嗎?');">首頁</a>


事件不一定要由使用者的操作觸發,你也可以直接呼叫方法來觸發事件。例如可以呼叫表單元素的submit()方法,如果在載入頁面時,想要讓第一個輸入欄位取得焦點,可以呼叫輸入欄位元素的focus()方法等。例如,如果某個輸入欄位id為user,則可以如下在載入後讓該欄位取得焦點:
window.onload = function() {
    document.getElementById('test').focus();
};