1. 程式人生 > >JS事件--事件處理程式之HTML事件處理程式

JS事件--事件處理程式之HTML事件處理程式

某個元素支援的每種事件,都可以使用一個與相應事件處理程式同名的HTML屬性來指定。這個特性的值應該是能夠執行的JavasScript程式碼。例如,要在按鈕被單擊時執行一些JavasScript,可以像下面這樣編寫程式碼:

<input type="button" value="Click me" onclick="alert('Clicked')" />

當單擊這個按鈕時,就會一個警告框。這個操作是通過指定onclick特性並將一些JavaScript程式碼作為它的值來定義的。由於 這個值是JavasScript,因此不能在其使用轉義的HTML語法字元,例如和號(&)、雙引號(“”),小於號(<)或大於號(>)。為了避免使用HTML實體,這裡使用了號。如果想要使用雙引號,那麼就要將程式碼改寫成如下所示:

<input type="button" value="Click me" onclick="alert(&quot;Clicked&quot;)" />

在HTML中定義的事件處理程式包含要執行的具體動作,也可以呼叫在頁面其他地方定義的指令碼,如下面例子所示:

<script type="text/javascript">
function showMessage() {
    alert("Hello world");
}
</script>
<input type="button" value="Click me" onclick
="showMessage()" />

在這個例子中,單擊按鈕就會呼叫showMessage()函式。這個函式是在一個獨立的

<!-- 輸出 "click" -->
<input type="button" value="Click me" onclick="alert(event.type)" />

通過event變數,可以直接訪問事件物件,你不用自己定義它,也不用從函式的引數列表中讀取。在這個函式內部,this值等於事件的目標元素,例如:

<!-- 輸出 "click" -->
<input type="button" value="Click me"
onclick="alert(this.value)" />

關於這個動態建立的函式,別一個有意思的地方是它擴充套件作用域的方式。在這個函式內部,可以像訪問區域性變數一樣訪問docment及該元素本身的成員。這個函式使用with像下面這樣擴充套件作用域:

function() {
    with(document) {
        with(this) {
            // 元素屬性值
        }
    }
}

如此一來,事件處理程式要訪問自己的屬性就簡單多了。下面這行程式碼與前端的例子效果相同:

<!-- 輸出 "click" -->
<input type="button" value="Click me" onclick="alert(value)" />

如果當前元素是一個表彰輸入元素,則作用域中還會包含訪問表單元素(父元素)的入口,這個函式就變成了如下所示:

function() {
    with(document) {
        with(this.form) {
            with(this) {
                // 元素屬性值
            }
        }
    }
}

實際上,這樣擴充套件作用域的方式,無非就是想讓事件處理程式無需引用表單就能訪問其他表單欄位。例如:

<form method="post">
    <input type="text" name="username" value=""/>
    <input type="button" value="Echo Username" onclick="alert(username.value)" >
</form>

在這個例子中,單擊按鈕會顯示文字框中的文字。值的注意的是,這裡直接引用了 username元素。

不過,在HTML中指定事件處理程式有兩缺點.首先,存在一個時差問題。因為使用者可能會在HTML元素一出現在頁面上就觸發相應的事件,但當時的事件處理程式有可能尚不具備執行條件。以前面的例子來說明,假設showMessage()函式是在按鈕下方、頁面的最底部定義的。如果使用者在頁面解析showMessage()函式之前就單擊了按鈕,就會引發 錯誤。為此,很多HTML事件處理程式會被封裝在try-catch塊中,以便錯誤不會浮出水面,如下面的例子所示:

<input type="button" value="Click me" onclick="try{showMessage();}catch(ex){}" />

這樣,如果在showMessage()函式有定義之前單擊了按鈕,使用者不會看到JavasScript錯誤,預設因為在瀏覽器有機會處理錯誤之前,錯誤就會被捕獲。

另一個缺點是,這樣擴充套件事件處理程式的作用域鏈在不同的瀏覽器中會導致不同結果。不同JavasScript引擎遵循的識別符號解析規則略有差異,很可能會訪問非限定物件成員時出錯。

通過HTML指定事件處理程式的最後一個缺點是HTML與JavasScript程式碼緊密耦合。如果要更換事件處理程式,就要改動兩個地方:HTML程式碼和JavasScript程式碼。而這正是許多開發人員摒棄HTML事件處理程式,轉而使用JavasScript指定事件處理程式的原因所在。