返回列表 發帖

jQuery 教學 - delegate 事件委派 (v1.4.2 以上適用)

這次要跟大家介紹的是 jQuery 1.4.2 新增的 delegate (事件委派),適合用在一次要綁定大量元素的事件時,可以減少記憶體的耗費並提昇綁定的效率。

[範例1]


首先請用滑鼠在以下方格上移動,看看這樣的效果:

上面的方格是一個大的 table,裡面每個 td 都被綁定了 hover 的事件,當滑鼠移過去時先漸漸增加透明度至 25%,之後再逐漸恢復。

如果是你會怎麼來處理呢?這樣嗎:
//方法 1
...
<td onmouseover="dosomething();"></td>
<td onmouseover="dosomething();"></td>
<td onmouseover="dosomething();"></td>
...
上面的方式當然是遜斃了,熟悉 jQuery 的人至少會用批次的方式來處理,像是:
//方法 2:找 #mytable 底下所有的 td,全部綁定 hover 事件
$("#mytable td").hover(function () {
    $(this).animate({opacity: 0.25}, 300, function () {
        $(this).animate({opacity: 1}, 300);
    });
});
方法 2 當然比方法 1 高明了一點,至少 code 維持了 jQuery 的風格,相當精簡。但是這樣的做法是讓每一個 td 都綁定了一個事件,缺點有兩個:

  • 綁定時,jQuery 會 loop 去處理,越多的元素要綁定時,會 loop 越多次,越花時間
  • 越多的元素綁定會越浪費記憶體


基於以上的原因,推薦你改用 delegate,綁定速度快,省記憶體,寫法只要稍稍改變一下,請看:
//方法 3:針對 #mytable 綁定 hover 事件,但是只對底下的 td 有效
$("#mytable").delegate("td", "hover", function () {
    $(this).animate({opacity: 0.25}, 300, function () {
        $(this).animate({opacity: 1}, 300);
    });
});
請直接對照方法 2 和方法 3 的程式碼第一行,寫法差異不大,但是效果真的差很多。如果一次有大量的元素需要綁定,建議改用 delegate 的語法。

此外,delegate 還有跟 live 一樣的效用,對於未來產生的新元素也是馬上讓綁定事件生效,以上面的例子,如果我在 table 動態增加兩行,新增的那兩行的所有 td 也會馬上有相同的動畫效果,相當不錯吧。


[範例2]


再來一個簡單的範例,介紹針對不同元素進行不同的處理。先看看 HTML 的部份:
<ul id="links">
    <li><a href="http://jsgears.com/">http://jsgears.com/</a></li>
    <li><a href="http://www.google.com/">http://www.google.com/</a></li>
    <li><a href="http://www.yahoo.com/">http://www.yahoo.com/</a></li>
</ul>
上面是幾個超連結的列表,沒有帶 target 的屬性,如果我要透過 JavaScript 來幫我達到點擊後另開視窗,同樣可以用 delegate 的方式,將事件綁定在 #link 並針對下面所有的 <a>,在事件處理的函式中,則針對個別 <a> 的 href 屬性去另開視窗。JavaScript 的部份如下:
$("#link").delegate("a", "click", function () {
    window.open($(this).attr("href"));
    return false;
});
跟一般事件處理函式一樣,在裡面使用 $(this) 表示被觸發事件的元素,透過讀取該元素的特定屬性,就可以針對不同元素進行不同的處理。

[Ending]


希望以上兩個範例夠清楚,能讓大家明白所謂「事件委派」的奧妙,我只需要把事件綁定在「一個」比較上層的元素,然後針對底下「多個」元素進行事件的處理,寫法和原本的事件綁定並沒有差異很大,但是使用得當的情況下,卻可以省下 client 端 browser 的許多資源。很不錯吧,趕快學起來,有機會用得上的~
To infinity and beyond!

好神奇……

原理是什麼?
I.WON'T.DIE

TOP

我想應該是綁定在上層元素的事件,會去判斷事件發生的原始點 (透過 e.target, e.srcElement),比對如果是符合要處理的元素,就進行處理。

實做的方法可以直接去看 jQuery 的原始碼。
To infinity and beyond!

TOP

受教了, 謝謝版大

TOP

我個人想法,我並沒有看原始碼…功力還不夠,

所有子元素的click事件會上傳到父元素,這條路是本來就已經鋪上了。


當按下按鈕時,javascript會去找所有您建立的click event,是否適用於該按鈕,並將該按鈕的事件往上傳

當按下按鈕時,
如果是一個一個建立的,
javascript要去找click event的數量就會多了一些,所以會比較慢。
如果是用delegate來建的,
javascript要去找click event的數量就少一些, 然後click事件上傳,父元素有被delegate,就看看是不是我們設定的元素,若是就觸發,可以說完全沒有做什麼尋找的動作。

雖然有種似懂非懂的感覺,最終還是得看原始碼才能了解。
Yi

TOP

返回列表 回復 發帖