jQuery 學習心得筆記 (3)

這篇主要介紹 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 可以寫成這樣:



jQuery Tutorial 1






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

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

UPDATE 100331: 在 jQuery 1.3 之後,你還可以使用 $.live 來 bind 「尚未出現」的元素,使用方式只需要將 bind 改成 live 即可。

  • lee

    教學真是清楚明瞭,期待您的下一篇!

  • shy

    [quote comment=””]教學真是清楚明瞭,期待您的下一篇![/quote]

  • 集思成

    [quote comment=””][quote comment=””]感謝您的分享~ 讓余人學習到了很多。有問題會在向閣下請教。[/quote][/quote]

  • TonyQ

    感謝您簡單明瞭的介紹.^^
    讓小弟也感覺到JQuery的方便之處.

  • 喬治撞到妮

    大大,你好~!
    有一個問題想請教~
    問題:就是如果有兩個一樣的div id名稱(只有class不一樣名字),而裡面假設有一個input(也有id),而我在要裡面塞值。

    $(“#inputid”).val(“值”); < #inputid”).val(“值”); <<–這樣子好像又不行耶~!!

    請問大大有解缺方案嗎??謝謝…

  • @喬治
    理論上同一個 page 裡你不該有兩個相同的 id…
    至於下面的 #inputid 應該就是這樣寫沒有問題的。

  • 喬治撞到妮

    RE~ericsk

    之所以會有兩個,是因為我使用jbox(jquery的plugins),它會在複製一份,只是我發現它會改它的class名字。
    而我使用的方法,很怪的事,ie兩個id都會填值,但ff不會,只會填一個。

  • axis

    舉個例,原本如下的語法:
    $(‘#btn’).click(showMsg);
    $(‘#btn2’).click(showMsg);

    卻要變成
    $(‘#btn’).bind(‘click’, showMsg);
    $(‘#btn’).trigger(‘foo’);]
    $(‘#btn2’).bind(‘click’, showMsg);
    $(‘#btn2’).trigger(‘foo’);

    就好像原本走直線可以到的目標,卻要拐好幾個彎才能到達

    還是不懂,用bind() and trigger()除了增加2倍的程式碼和維護難度外?
    好處在哪裡??

  • @axis
    bind/trigger 不是讓你用來處理本來就有做好的 helper (比方說您舉的 click event)
    想像一下你今天可能做了一個自己想像一下你今天可能做了一個自己的 UI,
    比方說是個 dialog,當 dialog 關閉時你可能想用一個事件來描述它或是處理之。
    這時候你也許就會想要自己讓某些物件 bind 住 ‘onDialogClosed’ 的 event,
    這樣等你關閉 dialog 時,就可以 trigger 自己定義出來的這個 event。

    (事實上在 jQuery UI 裡的 dialog 大概就是這樣的概念作的 :p)

  • axis

    另外本例中

    最後要重新顯示btn按鈕的這個動作

    $(‘#btn’).attr(‘disabled’, false);
    改用
    $(e.target).attr(‘disabled’, false);

    重新顯示btn按鈕這個動作不會發生,按鈕並不會回復到可按的狀態

    但是只要把e.target改回’#btn’ 後,就正常了

    我這邊運作的結果是這樣的

  • 喬治撞到妮

    $(document).ready(function(){
    //$(‘#aaa’).append(‘123456’).fadeIn(“slow”);
    //$(“a”).click(function () {
    $(“#aaa”).fadeIn(3000, function () {
    $(“#aaa1”).fadeIn(100);
    $(“#aaa_1”).fadeIn(3000, function () {
    $(“#aaa2”).fadeIn(100);
    });
    });
    // return false;
    //});

    });

    p { position:relative; width:400px; height:90px; }
    div { position:relative; width:400px; height:65px;
    font-size:36px; text-align:center;
    color:white; background:green;
    padding-top:25px;
    top:0; left:0; display:none; }
    span { display:none; }

    111!

    222!

    大大請問一下
    我上面的範例,主要是讓它有一直翻開的效果,但是這有缺點如果我不知道我有幾個的時候,會變成很長(很沒有彈性),請問有沒有更好的方式呢?

  • @喬治
    你可以把你要作用的 element 設成同一個 class, 然後利用 jQuery 的 selector 一次就可以把 fadeIn 的效果套用到所有選到 element。而不是用 id 一個一個select…

  • N

    請問前輩…
    有沒有用jquery 作過 cross site (domain)呢?

    因為小弟有個需求是要把認證訊息送到gateway上(例:10.0.0.1)
    geteway接收到會再傳至radius伺服器驗証..

    不曉得前輩有什麼想法或經驗可以指教一下呢?

  • @N
    您的需求看起來不能單單用 JavaScript 來作吧 Orz

  • N

    哦…
    我可能沒有說明清楚
    我只要能做到..我的網頁可以把URL變數傳到10.0.0.1,就可以了

    至於gateway那邊,機器會自己送

    之所以要這樣做
    是因為我想先進行帳號密碼是否有啟用(這部份OK)
    有啟用才送出ID跟PW給10.0.0.1
    因為之前在您這裡有看到cross domain的介紹
    所以問問您

  • 深入淺出,呵呵,又看完一章了。

    謝謝!

  • Hanley Towne

    很详细,也很耐心的分享,赞!

  • min

    您好,我剛初學jquery,
    $(e.target)這邊的”e”還是不太懂,它根本不會執行?

  • Pingback: jQuery 學習心得筆記(3) | ericsk.net - 熱點新聞網()