Javascript事件代理

什麼是事件代理?解釋下意義和原理

 

      JavaScript使用事件代理 JavaScript事件是所有網頁交互性的根基(我指的是真正的互動性,而不僅是那些CSS的下拉菜單)。

     在傳統的事件處理中,你按照需要爲每一個元素添加或者是刪除事件處理器。然而,事件處理器將有可能導致內存泄露或者是性能下降——你用得越多這種風險就越大。

     JavaScript事件代理則是一種簡單的技巧,通過它你可以把事件處理器添加到一個父級元素上,這樣就避免了把事件處理器添加到多個子級元素上

     事件代理用到了兩個在JavaSciprt事件中常被忽略的特性:事件冒泡以及目標元素

 

     當一個元素上的事件被觸發的時候,比如說鼠標點擊了一個按鈕,同樣的事件將會在那個元素的所有祖先元素中被觸發。這一過程被稱爲事件冒泡;這個事件從原始元素開始一直冒泡到DOM樹的最上層。對任何一個事件來說,其目標元素都是原始元素,在我們的這個例子中也就是按鈕。目標元素它在我們的事件對象中以屬性的形式出現。使用事件代理的話我們可以把事件處理器添加到一個元素上,等待事件從它的子級元素裏冒泡上來,並且可以很方便地判斷出這個事件是從哪個元素開始的。

 

      想象一下現在我們有一個10列、100行的HTML表格,你希望在用戶點擊某一單元格的時候做點什麼。比如說有一次我就需要讓表格中的每一個單元格在被點擊的時候變成可編輯狀態。如果把事件處理器加到這1000個單元格將會產生一個很大的性能問題,並且有可能導致內存泄露甚至是瀏覽器的崩潰。相反地,使用事件代理的話,你只需要把一個事件處理器添加到table元素上就可以了,這個函數可以把點擊事件給截下來,並且判斷出是哪個單元格被點擊了。

     代碼很簡單,我們所要關心的只是如何檢測目標元素而已。比方說我們有一個table元素,ID是“report”,我們爲這個表格添加一個事件處理器以調用editCell函數。

 editCell函數需要判斷出傳到table來的事件的目標元素。考慮到我們要寫的函數中可能會重複用到這一功能,所以我們把它單獨放到一個名爲getEventTarget的函數中:

 function getEventTarget(e) {

  e = e || window.event;

 return e.target || e.srcElement;

}    

 

    e這個變量表示的是一個事件對象,我們只需要寫一點點跨瀏覽器的代碼來返回目標元素。在IE裏目標元素放在srcElement屬性中,而在其它瀏覽器裏則是target屬性。

 接下來就是editCell函數了,這個函數調用到了getEventTarget函數。一旦我們得到了目標元素之後,剩下的事情就是看看它是否是我們所需要的那個元素了。

function editCell(e) {

 var target = getEventTarget(e);

 if(target.tagName.toLowerCase() === 'td') {

  // DO SOMETHING WITH THE CELL

 }

 }

 

    在editCell函數中,我們通過檢查目標元素標籤名稱的方法來確定它是否是一個表格的單元格。這種檢查也許過於簡單了點;如果它是這個目標元素單元格里的另一個元素呢?我們需要爲代碼做一點快速修改以便於其找出我們所需要的那個父級的td元素。如果說有些單元格不需要被編輯怎麼辦呢?此種情況下我們可以爲那些不可編輯的單元格添加一個指定的樣式名稱,然後在把單元格變成可編輯狀態之前先檢查它是否不包含那個樣式名稱。選擇總是多樣化的,你只需找到適合你應用程序的那一種就可以了。

 JavaScript事件代理帶來的好處有

 ◆那些需要創建的以及駐留在內存中的事件處理器少了。這是很重要的一點,我們得到了性能上的提升,同時降低了崩潰的風險。

 ◆在DOM更新後無須重新綁定事件處理器了。如果你的頁面是動態生成的,比如說通過Ajax,你不需要再在元素被載入或者卸載的時候來添加或者刪除事件處理器了。

 潛在的問題也許並不那麼明顯,但是一旦你注意到這些問題,你就可以輕鬆地避免它

 ◆你的事件管理代碼有成爲性能瓶頸的風險,所以儘量使它能夠短小精悍。

 不是所有的事件都能冒泡的。blur、focus、load和unload不能像其它事件一樣冒泡。事實上blur和focus可以用事件捕獲而非事件冒泡的方法獲得(在非IE的瀏覽器中) 

 ◆在管理鼠標事件的時候有些需要注意的地方。如果你的代碼處理mousemove事件的話

你遇上性能瓶頸的風險可就大了,因爲mousemove事件觸發得非常頻繁。而mouseout則因爲其怪異的表現而變得很難用事件代理來管理。

 已經有一些使用主流類庫的事件代理示例出現了,比如說用jQuery、Prototype以及Yahoo! UI的。你也可以找到那些不用任何類庫的例子,比如說Usable Type blog上的這一個。在你需要的時候,事件代理將成爲你工具箱裏一件得心應手的工具,而且它真的很容易實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章