全面瞭解 jQuery 事件

光光頭去打醬油發表於2016-06-08

在一個網頁內幾乎所有使用者互動都可以被 jQuery 作為事件撲捉到。事件具有非常重要的意義,可以讓你基於使用者動作做出適當的響應。例如,可以寫程式碼改變網頁的背景顏色,基於按鈕單擊或者滾動條滾動事件。

jQuery 有許多快捷方法,像 contextmenu()、hover() 和 keyup(),可以處理不同的事件。除了專門的方法,jQuery 還提供了通用的方法——on(‘eventName’, handler),方便你處理任何事件。牢記一點,這些方法只是在標準 DOM 事件外封裝了一層,你可以用原生 JavaScript 來處理這些事件。

在本教程中我們先簡單介紹這些事件方法,把這些方法分成五大類,然後來討論下工作時應遵循的最佳使用方式。

瀏覽器事件

瀏覽器事件有三種,分別是 error、resize 和 scroll。像 images 這樣的元素沒有正確載入的時候會觸發 error 事件。該快鍵方法在 jQuery 1.8 版本中被捨棄了,所以現在應該用 on(‘error’, handler) 方法來代替。

事件

瀏覽器視窗大小發生變化時會觸發 resize 事件。不同瀏覽器呼叫 resize 處理方法也不同。Internet Explorer 和 基於 WebKit 的瀏覽器能夠連續的呼叫處理方法,像 Opera 只能在 resize 事件最後呼叫。

下面的程式碼片段是根據視窗寬度改變 image src 屬性。

這個 CodePen demo 展示了此事件。

See the Pen The resize event by SitePoint (@SitePoint) on CodePen.

事件

在一個指定的元素中,當使用者滾動到不同的位置,可以關閉此事件。除了 window(視窗)物件,任何帶 scrollbar 的元素都能觸發此事件。例如,所有將 overflow 屬性設定為 scroll 的元素,或者任何可滾動的 iframe 可以觸發此事件。

the code below, we check if the user has scrolled down more than 500px and perform some actions.

請牢記,scroll 位置發生改變時,將呼叫處理方法。滾動的原因無關緊要。可能是按了方向鍵,單擊或者拖拽滾動條或者使用了滑鼠滾輪。在下面的程式碼,檢查使用者向下滾動是否超過 500px,然後觸發一些動作。

在下面的 CodePen demo 中,如果一直向下滾動快到底部的時候,應該會看到一條提醒,告訴你接近網頁底部了:

See the Pen The scroll event by SitePoint (@SitePoint) on CodePen.

載入事件

基於 document 或 DOM 狀態的三種事件,jQuery 有對應的方法,分別是 load、unload 和 ready。

load() 方法可以給任何元素加上一個處理方法,載入一個外部資源,比如圖片、指令碼、iframes 和 window 物件本身。當元素以及它所有的子元素都載入完該事件被觸發。該方法用在圖片載入的時候會有些問題。第一個就是 DOM 樹無法正確冒泡。第二個問題是不可靠也無法跨瀏覽器。

當使用者離開頁面時 unload 事件被觸發。使用者點選一個連結跳轉,在位址列中輸入新的 URL 或者關閉瀏覽器視窗都能導致此事件發生。還有重新載入頁面也會觸發。注意,使用 preventDefault() 方法無法取消 unload 事件。此外,在 unload 處理方法中呼叫 alert()、confirm() 和 prompt() 方法,大多數瀏覽器都會忽略這幾個方法,意味著下面的程式碼不會執行:

load() 和 unload() 在 1.8 版本中都被廢棄了。

The Ready Event

大多數情況下,如影象等所有元素無需完全載入就能正確執行指令碼。只要確定 DOM 樹構造完就行。ready 事件可以幫你解決。所有 ready 事件的處理方法只有在 DOM 載入完之後才能執行。在處理方法中可以執行 jQuery 程式碼或者將其他事件處理方法繫結到其他元素上。

下面的 CodePen demo 載入了一張高解析度圖片。你會發現 DOM 在圖片完全載入完之前就已經準備好了。

See the Pen The DOM ready event by SitePoint (@SitePoint) on CodePen.

如果程式碼依賴於一些 CSS 樣式屬性值,執行之前應該先提供各自引用的樣式或嵌入樣式。

Keyboard Events

keyboard(鍵盤) 事件是由使用者和鍵盤之間的互動觸發的。每個 keyboard 事件包含按鍵和事件型別資訊。jQuery 中有三個 keyboard 快捷方法——keydown()、keyup() 和 keypress()。

The Keyup and Keydown Events

正如其名,keyup 就是當使用者釋放鍵盤上的一個鍵觸發,keydown 就是按住鍵盤上一個鍵觸發。這些事件的處理方法可以繫結到任何元素上,但是隻有當前焦點元素才會被觸發。

推薦使用 event 物件中的 which 屬性來確定哪個鍵被按下了。實際上不同瀏覽器將不同資訊儲存在這個屬性中,jQuery 將 which 屬性進行了規範化為了方便可靠的檢索此資訊。

還有件事需要注意下,這些事件無法區分 a 和 shift+a 。後面的情況 shift 和 a 都是分別註冊的。在下面的程式碼,向使用者顯示一個彈出框並繫結了 keydown 事件。當按下 y 鍵,一個指定的元素將會從 DOM 中移除。

See the Pen The keydown event by SitePoint (@SitePoint) on CodePen.

The Keypress Event

keypress 事件和 keydown 事件非常相似。一個主要的區別就是修飾符和一些像 Shift 、Esc 等無法列印的鍵,不會觸發 keypress 事件。不應該用 keypress 事件捕捉像箭頭這類的特殊鍵。當你想知道輸入的是哪個字元,比如 A 或者 a ,一般可以使用 keypress 來處理。

下面的程式碼根據按下的鍵隱藏一個元素:

See the Pen The keypress event by SitePoint (@SitePoint) on CodePen.

Mouse Events

當使用者使用像滑鼠這種指點裝置時,mouse 事件會被觸發。該事件基於點選,如單擊、雙擊和右鍵快捷選單或者移動動作,如 mouseenter、mouseleave 和 mousemove。在本節中,將簡要地討論所有這些動作,包括一些演示,說明它們之間的細微差別。

Click-Based Events

jQuery 中定義了五種基於點選事件的方法。mousedown 和 mouseup 事件,從名字上顯而易見其意思,當使用者在一個元素上分別按住、釋放滑鼠按鍵就會觸發。另一方面,只有當滑鼠按鍵在指定元素上按住然後釋放才會觸發點選事件。

dblclick 稍微複雜一點。對於註冊為 dblclick 的事件,應該在系統限制時間前快速的點選兩次。不能給一個單獨的元素同時繫結單擊和雙擊的處理方法,對於雙擊事件的觸發瀏覽器的處理比較特殊。一些瀏覽器在雙擊之前可能會註冊兩個單獨的單擊事件,而其他瀏覽器在雙擊之前可能只註冊一個單擊事件。

在一個元素上右鍵單擊,在顯示內容選單前觸發 contextmenu 事件。這意味著處理方法中可以用程式碼阻止顯示預設選單。

下面的程式碼就阻止了右鍵單擊預設的選單顯示,而是顯示了一個自定義選單。

這個 demo 當圖片被點選就會使用新的 CSS 樣式,並且有一個自定義內容選單:

See the Pen The contextmenu event by SitePoint (@SitePoint) on CodePen.

Movement-Based Events

一些事件是基於滑鼠指標移動的,進入或離開元素。有六種基於滑鼠移動的事件。

讓我們從 mouseover 和 mouseenter 事件開始。正如名字的字面意思,當滑鼠指標進入一個元素的時候會觸發。類似的,滑鼠指標離開一個元素 mouseleave 和 mouseout 事件觸發。

mouseleave 和 mouseout 之間的一個區別就是前者滑鼠指標移出繫結的元素就會觸發。後者移出元素的任意後代元素也會觸發。mouseenter 和 mouseover 的不同也是一樣的(同理與 mouseleave 和 mouseout)。

See the Pen Mouse movement events by SitePoint (@SitePoint) on CodePen.


來看看基於滑鼠移動的 mouseenter 和 mouseover 事件是如何計數的。試著從右邊進入藍色的框中,在進入右邊粉色的框前停止。 現在 mouseenter 和 mouseover 的值都應該是 1 。如果繼續像左移動進入粉色框,mouseover 值變為 2。這是由於 mouseover 事件冒泡引起的。 粉色框的 mouseover 事件冒泡到外面的藍色框,所以 mouseover 事件計數增加 1。當繼續移動停在兩個粉色框之間,mouseover 事件再次被觸發。到達左邊的藍框時,mouseover
事件計數應該是 5 mouseenter 事件應該仍為 1。

同理可解釋 mouseleave 和 mouseout 事件計數。嘗試不同方向移動滑鼠看看計數如何變化。

The Mousemove and Hover Events

當滑鼠指標移入一個元素內 mousemove 事件觸發。每當有滑鼠移動就會觸發,即使移動距離小到只有一個畫素。因此,段時間內就可能觸發上百次。可以想象,在處理方法中執行復雜的操作會造成瀏覽器卡頓。明智的做法就是讓 mousemove 事件處理方法儘可能高效,當不需要的時候就解除繫結。

當滑鼠指標進入並離開元素才會觸發 hover。有兩種方法呼叫 hover 方法。第一種是:

當滑鼠指標移入元素時執行 handlerIn(),滑鼠指標移出時執行 handlerOut()。第二種方法是:

這次滑鼠指標移入移出元素時都執行 handlerInOut 方法。

See the Pen The hover and mousemove events by SitePoint (@SitePoint) on CodePen.


注意:該 demo 使用的 CSS 濾鏡效果不支援 IE。

Form Events

表單在網路中無所不在。幾乎每個使用者都填寫過一些表單。jQuery 有指定方法專門處理表單事件。 表單值改變或者丟失焦掉都可能觸發這些表單事件。有七種表單事件,一個一個來討論它們。

The Blur, Focus, Focusin and Focusout Events

當一個元素獲得焦點就會觸發 focus 事件。只適合表單元素和錨標籤。想觸發其他元素的 focus 事件需要設定元素的 tabindex 屬性。記住,在 IE 瀏覽器中給隱藏元素設定 focus 事件將導致錯誤。如果一定要觸發沒有設定 focus 的元素的 focus 事件,可以呼叫 triggerHandler( “focus” ) 方法。

blur 事件當元素失去焦點時觸發。對於老版本的瀏覽器此事件只適用於表單元素。

不像 focus 事件,focusin 事件無論何時無論什麼元素或者它的後代元素獲取焦點都能觸發。類似的,focusout 當元素或者它的後代元素失去焦點時觸發。所以,如果你想利用事件冒泡的話,你應該使用這兩個事件。

The Select, Change and Submit Events

當一個元素值改變了會觸發 change 事件。此事件只適用於 、 和 元素。在 checkboxes、radio buttons 和 select boxes 情況下,使用者做了任何選擇就會觸發 change 事件。對於其他元素就只有失去焦點的時候才會觸發。注意,如果使用 JavaScript 改變 input 元素的值無法觸發 change 事件。

當使用者在一個元素中選擇文字觸發 select 事件。此事件範圍有限,只適用於 和 元素。如果想要檢索所選的文字,需要使用一個跨瀏覽器 jQuery 外掛。

當使用者要提交表單時觸發 submit 事件。只能將處理方法繫結在表單元素上。使用者點選 、 或者 元素時會觸發該事件。有趣的是在 IE 瀏覽器中 JavaScript submit 事件不會冒泡。不過,這個行為在 jQuery 1.4 版本中已經做了跨瀏覽器規範化。

See the Pen Form events by SitePoint (@SitePoint) on CodePen.

Changes in jQuery 3

load、error 和 unload 方法已經在 jQuery 1.8 版本中捨棄。load() 方法本質上不太明確。這個方法既可以是 AJAX 載入或者是普通載入事件。類似的,error 方法和 jQuery.error() 方法會混淆。現在 jQuery 3 中這些方法最終被移除。現在必須給這些方法註冊監聽器來使用。

Final Thoughts

在這篇文章中,基本上覆蓋了所有 jQuery 主要的事件方法,還有這些事件之間的差異和相同之處。知道什麼時候使用 keypress 代替 keydown 可以幫助你避免麻煩和節省寶貴的時間。儘管可以用原生的 JavaScript 在 DOM 事件中新增 hook,jQuery 對跨瀏覽器的一些差異做了規範化,意味著網站、應用能支援更多瀏覽器,這是一個優勢。

想了解更多事件可以訪問 jQuery 官方文件。如果有關於 jQuery 使用中的任何問題或建議,請發表評論。

相關文章