這篇主要介紹 jQuery 的事件(Event)處理。

上一篇用了一個簡單的例子介紹了用 jQuery 來操作網頁元件的感覺,現在來重新看這個例子做的事情:

「按下按鈕,然後在 id 為 msg 的網頁元件中顯示 “hello” 字樣」

,在這樣的情境下,按鈕產生了一個「按下」(click) 的事件(event),而我們在 HTML 裡使用 onclick 來定義該按鈕在 click 這個 event 發生時,要去呼叫 showMsg() 這個函式,完成一個 click 事件處理流程。在一個 web application 之中,幾乎所有事情都跟 event 有關,很多 JavaScript framework 都會作一些 event handling 的函式,方便你在各瀏覽器間一致化處理的動作。不過既然這篇是要介紹 jQuery/Event,那當然就只會寫 jQuery 裡的東西囉。

上一篇文章的 HTML 可以寫成這樣:

<html>
  <head>
    <title>jQuery Tutorial 1</title>
    <script type="text/javascript" src="jquery-1.2.1.min.js"></script>
    <script type="text/javascript">
      function showMsg(e) {
        $(e.target).attr('disabled', true);
        if ($('#msg').html().length == 0) {
            $('#msg').html('<h1>Hello</h1>');
        }
        $('#msg').fadeIn();
        setTimeout(function(){
            $('#msg').fadeOut();
            $(e.target).attr('disabled', false);
        }, 3000);
      }

      $(document).ready(function(e){
          $('#btn').click(showMsg);
      });
    </script>
  </head>
  <body>
    <div id="msg"></div>
    <input type="button" value="Click Me" id="btn"/>
  </body>
</html>

在這個份改寫過的 code 裡面,你可以注意 <body>...</body> 之間已經沒有 JavaScript 的程式碼了,完全只是定義了網頁元件而已,所有跟 JavaScript 有關的東西已經被我拉到 <script>...</script> 之中了,這也代表說,你可以把這些程式碼放到另外一個 js 檔再 include 進來使用,讓這個 HTML 檔更為乾淨(?)

先來說一下 $(document).ready 這個部份,使用 $(document).ready 所代表的意義就是:「當頁面讀取完畢之後的 event」,裡面的參數是一個 function,這類 function 通常會叫它 callback (function),所以在這裡我傳入一個 function,表示當頁面讀取完畢後,就呼叫這個函式做事情。$(document).ready 在這裡相當於 <body> 的 load event,所以也可以寫成 $('body').load(....);

所以這裡就可以看出,在 jQuery 裡要定義一個物件面對不同 event 時的處理動作,就是運用 $ 把網頁元件變成 jQuery 物件後,再透過 jQuery/Event 的這些函式來定義不同 event 的處理行為,所以,當頁面讀取完畢後,我做了一個動作:

「讓 id 為 “btn” 的元件,當它碰到 click event 的時候,去作 showMsg」

,這就是 $('#btn').click(showMsg); 所代表的意義,所以即便我在按鈕的 HTML 中沒有寫 onclick 時要做什麼,但還是能夠完成我們要它完成的事情(去呼叫 showMsg)。

再來看看這裡的 showMsg 定義,這裡可以看到我把它做了一點小修改,showMsg 多了一個參數 e,這是用來表示 event 的物件,因為在 jQuery 的 event handling functions 裡,它會將 event 的物件傳到 callback function 中,於是,我就能夠使用 e.target 來拿到觸發這個 event 的網頁元件了(在這裡就是那顆按鈕)。不過這裡要注意的是,e 這個物件並不是 jQuery 的物件,當然 e.target 也不是,所以若是要對這個物件做 jQuery 定義的函式,那就別忘了用 $() 把它轉成 jQuery 的物件就可以了。看吧,jQuery 的 selector 真是超好用的!

bind() and trigger()

上述的程式碼,用到了 jQuery 定義好的 click 函式來進行 click event 的處理,而 jQuery 也把網頁上預設的 event 都作了相關的 function,不過 jQuery 同時也提供了一個更一般化(general)的 function — bind 來作 event handling 的定義,因為這就好像把某個元件「綁」在某個 event 之下(當 event 發生時去做該做的事),所以上面定義按鈕的 click event handling 可以改寫成這樣:

$('#btn').bind('click', showMsg);

也就是把 event 的名稱傳入 bind 的第一個參數,然後一樣要丟進一個 callback function,這樣才知道要做什麼事。不過既然 jQuery 都幫我們把網頁上會發生的 event 都定義好相關的 function 了,那為什麼還需要 bind() 呢?一方面除了將 event 的名字參數化以外,更重要的意義在於:可以自訂 event。

自訂 event 的好處就在於,你可以把物件任意地 bind 於某個 event 上(假設這個 event 叫 foo),所以寫成:

$('#btn').bind('foo', showMsg);

但這個名為 foo 的 event 在正常的網頁操作下並不會產生,所以這時就得借助 trigger 這個 function 了,用法如下:

...
/* 送給 #btn 一個 foo 的 event */
$('#btn').trigger('foo');
...

就這樣,#btn 會收到一個 foo 的 event,然後根據它 bind 於 foo event 上的定義,接下來就會去呼叫 showMsg 了,jQuery 的 event 處理其實就這麼簡單。

另外,雖然已經用 bind() 定義好綁在某個 event 下的物件可以再運用 unbind() 函式來讓它「掙脫束縳」,不過如果只是想被 event 驅動一次,也可以利用 jQuery 的 one 函式來做 bind 的動作(用法與 bind() 相同),這樣當它被 trigger 一次之後就不會再綁在這個 event 下了。

toggle() 則是用來開關 被 trigger 時要不要執行 callback 的。

這裡可以看一下 jQuery 提供了哪些 Event handling 的 function。