jQuery代碼優(yōu)化之基本事件
更新時間:2011年11月01日 17:05:02 作者:
jQuery對事件系統(tǒng)的抽象與優(yōu)化也是它的一大特色。本文僅從事件系統(tǒng)入手,簡要分析一下jQuery為什么提供mouseenter和mouseleave事件,它們與標(biāo)準(zhǔn)的mouseover、mouseout事件有什么區(qū)別
事件模型
說到事件,就要追溯到網(wǎng)景與微軟的“瀏覽器大戰(zhàn)”了。當(dāng)時,事件模型還沒有標(biāo)準(zhǔn),兩家公司的實現(xiàn)就是事實標(biāo)準(zhǔn)。網(wǎng)景在Navigator中實現(xiàn)了“事件捕獲”的事件系統(tǒng),而微軟則在IE中實現(xiàn)了一個基本上相反的事件系統(tǒng),叫做“事件冒泡”。這兩種系統(tǒng)的區(qū)別在于當(dāng)事件發(fā)生時,相關(guān)元素處理(響應(yīng))事件的優(yōu)先權(quán)不同。
下面舉例說明這兩種事件機制的區(qū)別。假設(shè)文檔中有如下結(jié)構(gòu):
<div>
<span>
<a>...</a>
</span>
</div>
因為這三個元素是嵌套的,所以單擊了a,實際上也就單擊了span和div。換句話說,這三個元素都應(yīng)該有處理單擊事件的機會。在事件捕獲機制下,處理這個單擊事件的優(yōu)先次序是:div > span > a;而在事件冒泡機制下,處理這個單擊事件的優(yōu)先次序則是:a > span > div。
后來,W3C的規(guī)范要求瀏覽器同時支持捕獲和冒泡機制,并允許開發(fā)人員選擇把事件注冊到哪個階段。于是就有了下面這個注冊事件的標(biāo)準(zhǔn)方法:
target.addEventListener(type, listener, useCapture Optional );
其中:
◆ type:字符串,表示監(jiān)聽的事件類型
◆ listener:監(jiān)聽器對象(JavaScript函數(shù)),在指定事件發(fā)生時可以收到通知
◆ useCapture:布爾值,是否注冊到捕獲階段
在實際應(yīng)用開發(fā)中,為了確保與IE(因為它不支持捕獲)兼容,useCapture一般都指定為false(默認(rèn)值也是false)。換句話說,只把事件注冊到冒泡階段;對于上面那個簡單的例子來說,響應(yīng)順序就是:a > span > div。
冒泡的副作用
如前所述,IE的冒泡事件模型基本上成為了事實標(biāo)準(zhǔn)。但冒泡有一個副作用。
仍以前面的文檔結(jié)構(gòu)為例,假設(shè)它是界面中的一個菜單項,我們希望用戶鼠標(biāo)離開div時隱藏菜單。于是,我們給div注冊了一個mouseout事件。如果用戶鼠標(biāo)是從div離開的,那么一切正確。而如果用戶鼠標(biāo)是從a或span離開的,問題就來了。因為由于事件冒泡,從這兩個元素開始分派的mouseout事件都會傳播到div,從而導(dǎo)致鼠標(biāo)并沒有離開div,菜單就提前隱藏了。
當(dāng)然,冒泡的副作用不難避免。比如,給div內(nèi)部的每個元素都注冊mouseout事件,并使用.stopPropagation()方法阻止事件進一步傳播。對于IE,就得將事件對象的cancelBubble屬性設(shè)置為false,取消事件冒泡。不過,這仍然回到自己處理瀏覽器不兼容性問題的老路上了。
優(yōu)化方案
為了避免冒泡的副作用,jQuery提供了mouseenter和mouseleave事件,就使用它們來代替mouseover和mouseout吧。
下面這個摘自jQuery的內(nèi)部函數(shù)withinElement,就是為mouseenter和mouseleave提供支持的。翻譯了一下注釋,僅供大家參考。
// 下面這個函數(shù)用于檢測事件是否發(fā)生在另一個元素的內(nèi)部
// 在 jQuery.event.special.mouseenter 和 mouseleave 處理程序中使用
var withinElement = function( event ) {
// 檢測 mouse(over|out) 是否還在相同的父元素內(nèi)
var parent = event.relatedTarget;
// 設(shè)置正確的事件類型
event.type = event.data;
// Firefox 有時候會把 relatedTarget 指定一個 XUL 元素
// 對于這種元素,無法訪問其 parentNode 屬性
try {
// Chrome 也類似,雖然可以訪問 parentNode 屬性
// 但結(jié)果卻是 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 );
}
// 假定已經(jīng)離開了元素,因為很可能鼠標(biāo)放在了一個XUL元素上
} catch(e) { }
},
結(jié)論
在jQuery里,可以使用mouseenter和mouseleave事件來避免事件冒泡的副作用。
原文:http://www.ituring.com.cn/article/420
說到事件,就要追溯到網(wǎng)景與微軟的“瀏覽器大戰(zhàn)”了。當(dāng)時,事件模型還沒有標(biāo)準(zhǔn),兩家公司的實現(xiàn)就是事實標(biāo)準(zhǔn)。網(wǎng)景在Navigator中實現(xiàn)了“事件捕獲”的事件系統(tǒng),而微軟則在IE中實現(xiàn)了一個基本上相反的事件系統(tǒng),叫做“事件冒泡”。這兩種系統(tǒng)的區(qū)別在于當(dāng)事件發(fā)生時,相關(guān)元素處理(響應(yīng))事件的優(yōu)先權(quán)不同。
下面舉例說明這兩種事件機制的區(qū)別。假設(shè)文檔中有如下結(jié)構(gòu):
復(fù)制代碼 代碼如下:
<div>
<span>
<a>...</a>
</span>
</div>
因為這三個元素是嵌套的,所以單擊了a,實際上也就單擊了span和div。換句話說,這三個元素都應(yīng)該有處理單擊事件的機會。在事件捕獲機制下,處理這個單擊事件的優(yōu)先次序是:div > span > a;而在事件冒泡機制下,處理這個單擊事件的優(yōu)先次序則是:a > span > div。
后來,W3C的規(guī)范要求瀏覽器同時支持捕獲和冒泡機制,并允許開發(fā)人員選擇把事件注冊到哪個階段。于是就有了下面這個注冊事件的標(biāo)準(zhǔn)方法:
target.addEventListener(type, listener, useCapture Optional );
其中:
◆ type:字符串,表示監(jiān)聽的事件類型
◆ listener:監(jiān)聽器對象(JavaScript函數(shù)),在指定事件發(fā)生時可以收到通知
◆ useCapture:布爾值,是否注冊到捕獲階段
在實際應(yīng)用開發(fā)中,為了確保與IE(因為它不支持捕獲)兼容,useCapture一般都指定為false(默認(rèn)值也是false)。換句話說,只把事件注冊到冒泡階段;對于上面那個簡單的例子來說,響應(yīng)順序就是:a > span > div。
冒泡的副作用
如前所述,IE的冒泡事件模型基本上成為了事實標(biāo)準(zhǔn)。但冒泡有一個副作用。
仍以前面的文檔結(jié)構(gòu)為例,假設(shè)它是界面中的一個菜單項,我們希望用戶鼠標(biāo)離開div時隱藏菜單。于是,我們給div注冊了一個mouseout事件。如果用戶鼠標(biāo)是從div離開的,那么一切正確。而如果用戶鼠標(biāo)是從a或span離開的,問題就來了。因為由于事件冒泡,從這兩個元素開始分派的mouseout事件都會傳播到div,從而導(dǎo)致鼠標(biāo)并沒有離開div,菜單就提前隱藏了。
當(dāng)然,冒泡的副作用不難避免。比如,給div內(nèi)部的每個元素都注冊mouseout事件,并使用.stopPropagation()方法阻止事件進一步傳播。對于IE,就得將事件對象的cancelBubble屬性設(shè)置為false,取消事件冒泡。不過,這仍然回到自己處理瀏覽器不兼容性問題的老路上了。
優(yōu)化方案
為了避免冒泡的副作用,jQuery提供了mouseenter和mouseleave事件,就使用它們來代替mouseover和mouseout吧。
下面這個摘自jQuery的內(nèi)部函數(shù)withinElement,就是為mouseenter和mouseleave提供支持的。翻譯了一下注釋,僅供大家參考。
復(fù)制代碼 代碼如下:
// 下面這個函數(shù)用于檢測事件是否發(fā)生在另一個元素的內(nèi)部
// 在 jQuery.event.special.mouseenter 和 mouseleave 處理程序中使用
var withinElement = function( event ) {
// 檢測 mouse(over|out) 是否還在相同的父元素內(nèi)
var parent = event.relatedTarget;
// 設(shè)置正確的事件類型
event.type = event.data;
// Firefox 有時候會把 relatedTarget 指定一個 XUL 元素
// 對于這種元素,無法訪問其 parentNode 屬性
try {
// Chrome 也類似,雖然可以訪問 parentNode 屬性
// 但結(jié)果卻是 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 );
}
// 假定已經(jīng)離開了元素,因為很可能鼠標(biāo)放在了一個XUL元素上
} catch(e) { }
},
結(jié)論
在jQuery里,可以使用mouseenter和mouseleave事件來避免事件冒泡的副作用。
原文:http://www.ituring.com.cn/article/420
相關(guān)文章
ASP.NET中基于JQUERY的高性能的TreeView補充
根據(jù) 假正經(jīng)哥哥 的博客整理,我第一次使用的另外的TREEVIEW,可是 做出來的效果 太卡,不知道什么原因。這次用的假正經(jīng)哥哥的這篇文章。2011-02-02Jquery Ajax解析XML數(shù)據(jù)(同步及異步調(diào)用)簡單實例
本篇文章主要是對Jquery Ajax解析XML數(shù)據(jù)(同步及異步調(diào)用)的簡單實例進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-02-02為jquery的ajax請求添加超時timeout時間的操作方法
這篇文章主要介紹了為jquery的ajax請求添加超時timeout時間的操作方法,文中通過一段簡單的代碼給大家介紹jquery ajax超時設(shè)置方法,感興趣的朋友跟隨腳本之家小編一起看看吧2018-09-09