jQuery程式碼優化:基本事件篇
jQuery對事件系統的抽象與優化也是它的一大特色。本文僅從事件系統入手,簡要分析一下jQuery為什麼提供mouseenter和mouseleave事件,它們與標準的mouseover、mouseout事件有什麼區別。
事件模型
說到事件,就要追溯到網景與微軟的“瀏覽器大戰”了。當時,事件模型還沒有標準,兩家公司的實現就是事實標準。網景在Navigator中實現了“事件捕獲”的事件系統,而微軟則在IE中實現了一個基本上相反的事件系統,叫做“事件冒泡”。這兩種系統的區別在於當事件發生時,相關元素處理(響應)事件的優先權不同。
下面舉例說明這兩種事件機制的區別。假設文件中有如下結構:
<div>
<span>
<a>...</a>
</span>
</div>
因為這三個元素是巢狀的,所以單擊了a,實際上也就單擊了span和div。換句話說,這三個元素都應該有處理單擊事件的機會。在事件捕獲機制下,處理這個單擊事件的優先次序是:div > span > a;而在事件冒泡機制下,處理這個單擊事件的優先次序則是:a > span > div。
後來,W3C的規範要求瀏覽器同時支援捕獲和冒泡機制,並允許開發人員選擇把事件註冊到哪個階段。於是就有了下面這個註冊事件的標準方法:
target.addEventListener(type, listener, useCapture Optional );
其中:
- type:字串,表示監聽的事件型別
- listener:監聽器物件(JavaScript函式),在指定事件發生時可以收到通知
- useCapture:布林值,是否註冊到捕獲階段
在實際應用開發中,為了確保與IE(因為它不支援捕獲)相容,useCapture一般都指定為false(預設值也是false)。換句話說,只把事件註冊到冒泡階段;對於上面那個簡單的例子來說,響應順序就是:a > span > div。
冒泡的副作用
如前所述,IE的冒泡事件模型基本上成為了事實標準。但冒泡有一個副作用。
仍以前面的文件結構為例,假設它是介面中的一個選單項,我們希望使用者滑鼠離開div時隱藏選單。於是,我們給div註冊了一個mouseout事件。如果使用者滑鼠是從div離開的,那麼一切正確。而如果使用者滑鼠是從a或span離開的,問題就來了。因為由於事件冒泡,從這兩個元素開始分派的mouseout事件都會傳播到div,從而導致滑鼠並沒有離開div,選單就提前隱藏了。
當然,冒泡的副作用不難避免。比如,給div內部的每個元素都註冊mouseout事件,並使用.stopPropagation()方法阻止事件進一步傳播。對於IE,就得將事件物件的cancelBubble屬性設定為true,取消事件冒泡。不過,這仍然回到自己處理瀏覽器不相容性問題的老路上了。
優化方案
為了避免冒泡的副作用,jQuery提供了mouseenter和mouseleave事件,就使用它們來代替mouseover和mouseout吧。
下面這個摘自jQuery的內部函式withinElement,就是為mouseenter和mouseleave提供支援的。翻譯了一下注釋,僅供大家參考。
// 下面這個函式用於檢測事件是否發生在另一個元素的內部
// 在 jQuery.event.special.mouseenter 和 mouseleave 處理程式中使用
var withinElement = function( event ) {
// 檢測 mouse(over|out) 是否還在相同的父元素內
var parent = event.relatedTarget;
// 設定正確的事件型別
event.type = event.data;
// Firefox 有時候會把 relatedTarget 指定一個 XUL 元素
// 對於這種元素,無法訪問其 parentNode 屬性
try {
// Chrome 也類似,雖然可以訪問 parentNode 屬性
// 但結果卻是 null
if ( parent && parent !== document && !parent.parentNode ) {
return;
}
// 沿 DOM 樹向上
while ( parent && parent !== this ) {
parent = parent.parentNode;
}
if ( parent !== this ) {
// 如果實際正好位於一個非子元素上面,那好,就處理事件
jQuery.event.handle.apply( this, arguments );
}
// 假定已經離開了元素,因為很可能滑鼠放在了一個XUL元素上
} catch(e) { }
},
結論
在jQuery裡,可以使用mouseenter和mouseleave事件來避免事件冒泡的副作用。
(注:本文基於《jQuery基礎教程(第3版)》相關章節內容編撰而成。)
相關連結:
相關文章
- jQuery程式碼優化:事件委託篇jQuery優化事件
- jQuery程式碼優化:遍歷篇jQuery優化
- jQuery程式碼優化:選擇符篇jQuery優化
- jQuery高階技巧——效能優化篇jQuery優化
- jQuery基本功能——事件jQuery事件
- jQuery的change事件程式碼演示jQuery事件
- jQuery事件冒泡程式碼例項jQuery事件
- 基於jquery的頁面程式碼的優化jQuery優化
- Android效能優化篇:從程式碼角度進行優化Android優化
- jQuery阻止事件冒泡程式碼例項jQuery事件
- 阻止jquery事件冒泡程式碼例項jQuery事件
- jQuery阻止事件冒泡例項程式碼jQuery事件
- jquery複習之路---事件篇jQuery事件
- 前端效能JQuery篇之選擇器優化前端jQuery優化
- 程式碼優化優化
- jQuery阻止事件冒泡現象程式碼例項jQuery事件
- jQuery點選回車事件程式碼例項jQuery事件
- jquery自定義事件簡單例項程式碼jQuery事件單例
- jquery效能優化jQuery優化
- 效能優化——記憶體洩漏(3)程式碼分析篇優化記憶體
- 【調優篇基本原理】優化器相關引數配置優化
- javaScript程式碼優化JavaScript優化
- Java程式碼優化Java優化
- 效能優化篇 - js事件迴圈機制(event loop)優化JS事件OOP
- jQuery阻止事件冒泡和預設行為程式碼jQuery事件
- 優化If else(簡化程式碼)優化
- Android效能優化——程式碼優化(一)Android優化
- jQuery 效能優化技巧jQuery優化
- Android 程式碼優化Android優化
- iOS程式碼效能優化iOS優化
- MySQL優化基本操作MySql優化
- 效能優化篇優化
- jQuery模擬實現滑鼠點選事件程式碼例項jQuery事件
- 使用Web Worker優化程式碼Web優化
- Android Note - 程式碼優化Android優化
- 重構 - 程式碼優化技巧優化
- DeviceMotionEvent程式碼優化例項dev優化
- 分散式佇列程式設計優化篇分散式佇列程式設計優化