讀jQuery之十一 添加事件核心方法
add: function( elem, types, handler, data ) {
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
...
}
定義了四個(gè)參數(shù)elem、types、handler和data分別為HTMLElement、事件類型(如click)、事件響應(yīng)函數(shù)、數(shù)據(jù)。此外,types 可以以空格分開(kāi)傳多種事件("mouseover mouseout")。handler 有時(shí)會(huì)是一個(gè)對(duì)象(實(shí)現(xiàn)live時(shí))。data 最后會(huì)掛在擴(kuò)充后的event對(duì)象上,即作為event的屬性。而event會(huì)在handler作為第一個(gè)參數(shù)拿到,這樣也就可以在handler拿到data了。
下面詳細(xì)說(shuō)明
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
文本和注釋節(jié)點(diǎn)直接返回。
if ( handler === false ) {
handler = returnFalse;
} else if ( !handler ) {
// Fixes bug #7229. Fix recommended by jdalton
return;
}
參數(shù)handler為false時(shí),將handler賦值為returnFalse,returnFalse為一個(gè)函數(shù),如下
function returnFalse() {
return false;
}
jQuery通過(guò)handler為false來(lái)阻止元素默認(rèn)行為,停止事件冒泡。這個(gè)需要結(jié)合jQuery.event.handle看。
var handleObjIn, handleObj;
if ( handler.handler ) {
handleObjIn = handler;
handler = handleObjIn.handler;
}
// Make sure that the function being executed has a unique ID
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}
定義變量handleObjIn,handleObj。
handler從字面上看是事件響應(yīng)(回調(diào))函數(shù),但這里出現(xiàn)handler.handler,讓人倍感怪異。即什么時(shí)候會(huì)將handler當(dāng)一個(gè)JS對(duì)象傳入呢?
多數(shù)時(shí)候傳的還是Function類型的,看看源碼中jQuery.event.add的調(diào)用可發(fā)現(xiàn)jQuery在實(shí)現(xiàn)live的時(shí)候會(huì)傳Object類型。如下
add: function( handleObj ) {
jQuery.event.add( this,
liveConvert( handleObj.origType, handleObj.selector ),
jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
},
這時(shí)會(huì)把handleObjIn賦值為所傳的JS對(duì)象,真正的handler 卻是handleObjIn.handler。這話有點(diǎn)繞,慢慢體會(huì)。
// Make sure that the function being executed has a unique ID
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}
所傳參數(shù)handler添加個(gè)屬性guid,為一個(gè)數(shù)字,自增的從1開(kāi)始。即使用jQuery添加事件,會(huì)為事件響應(yīng)函數(shù)默認(rèn)的添加了屬性guid。這個(gè)guid再刪除事件時(shí)會(huì)用到。
// Init the element's event structure
var elemData = jQuery._data( elem );
先取elemData,這里使用了前面提到的jQuery._data。第一次為HTMLElement添加事件是elemData是個(gè)空對(duì)象({})。
// If no elemData is found then we must be trying to bind to one of the
// banned noData elements
if ( !elemData ) {
return;
}
elemData不存在則直接返回。
var events = elemData.events,
eventHandle = elemData.handle;
定義events,eventHandle。同樣第一次時(shí)這兩個(gè)變量都是undefined。
if ( !events ) {
elemData.events = events = {};
}
if ( !eventHandle ) {
elemData.handle = eventHandle = function( e ) {
// Discard the second event of a jQuery.event.trigger() and
// when an event is called after a page has unloaded
return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
jQuery.event.handle.apply( eventHandle.elem, arguments ) :
undefined;
};
}
給elemData.events和elemData.handle賦值。
// Add elem as a property of the handle function
// This is to prevent a memory leak with non-native events in IE.
eventHandle.elem = elem;
暫存elem到eventHandle,刪除事件注冊(cè)時(shí)會(huì)將其置null,避免部分瀏覽器中內(nèi)存泄露。
// Handle multiple events separated by a space
// jQuery(...).bind("mouseover mouseout", fn);
types = types.split(" ");
將字符串以空格為切割符轉(zhuǎn)成數(shù)組。這句使其可以一次添加多個(gè)事件,多個(gè)事件的handler是相同的。
后面是一個(gè)while循環(huán)
while ( (type = types[ i++ ]) ) {
handleObj = handleObjIn ?
jQuery.extend({}, handleObjIn) :
{ handler: handler, data: data };
...
}
循環(huán)數(shù)組,里面依次處理如下
, 取得handleObj
, 處理事件命名空間,以點(diǎn)號(hào)(.)來(lái)區(qū)別。如果type有點(diǎn)號(hào),則具有命名空間,否則沒(méi)有
, 給handlerObj添加type,guid屬性。這些后續(xù)刪除事件時(shí)用到
, 取到handlers,special。多數(shù)情況下使用addEventListener/attachEvent來(lái)添加事件。從變量special可看出對(duì)于特殊的事件如ready,beforeunload及l(fā)ive事件是特殊處理的。 ready 調(diào)用的是jQuery.bindReady,而jQuery.bindReady內(nèi)部調(diào)用的仍然是 addEventListener/attachEvent。beforeunload則是使用window.onbeforeunload來(lái)添加。live是實(shí)現(xiàn)事件代理的,他的處理也是特殊的。
, 最后吧handleObj添加到數(shù)組handles中。
jQuery.event.add 的最后一句,解決IE中內(nèi)存泄露。
// Nullify elem to prevent memory leaks in IE
elem = null;
jQuery事件管理的數(shù)據(jù)結(jié)構(gòu),我做了個(gè)圖。如下

相關(guān)文章
仿新浪微博返回頂部的jquery實(shí)現(xiàn)代碼
在web頁(yè)面中,如果頁(yè)面較高,為了方便用戶快速地返回頂部,都會(huì)添加一個(gè)返回頂部按鈕2012-10-10jQuery插件FusionWidgets實(shí)現(xiàn)的Cylinder圖效果示例【附demo源碼】
這篇文章主要介紹了jQuery插件FusionWidgets實(shí)現(xiàn)的Cylinder圖效果,結(jié)合實(shí)例形式分析了jQuery使用FusionWidgets結(jié)合swf文件讀取xml數(shù)據(jù)并采用Cylinder圖展示的相關(guān)實(shí)現(xiàn)技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2017-03-03jquery插件開(kāi)發(fā)之實(shí)現(xiàn)jquery手風(fēng)琴功能分享
需要一個(gè)手風(fēng)琴效果,就動(dòng)手寫(xiě)了一個(gè)。其實(shí)有多個(gè)現(xiàn)成的jQuery手風(fēng)琴插件可以用,但對(duì)比了一下,總感覺(jué)有些笨重,還是自己寫(xiě)的脈絡(luò)自己最清楚,擴(kuò)展起來(lái)也更容易些2014-03-03jQuery編寫(xiě)網(wǎng)頁(yè)版2048小游戲
本文主要分享了jQuery編寫(xiě)網(wǎng)頁(yè)版2048小游戲的示例代碼,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01jquery+php實(shí)現(xiàn)搜索框自動(dòng)提示
百度上有個(gè)很使用的功能,就是用戶在搜索的時(shí)候會(huì)自動(dòng)提示相關(guān)搜索條件以供選擇,非常人性化的設(shè)計(jì),我們?nèi)绾螌⒋斯δ芊诺阶约旱捻?xiàng)目中呢,經(jīng)過(guò)一番研究,終于實(shí)現(xiàn)了此功能,分享給大家。2014-11-11jquery實(shí)現(xiàn)垂直手風(fēng)琴菜單
這篇文章主要為大家詳細(xì)介紹了jquery實(shí)現(xiàn)垂直手風(fēng)琴菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03jQuery實(shí)現(xiàn)模糊搜索功能的方法分析
這篇文章主要介紹了jQuery實(shí)現(xiàn)模糊搜索功能的方法,結(jié)合實(shí)例形式總結(jié)分析了jQuery關(guān)鍵字搜索、模糊查詢、動(dòng)態(tài)刪除table數(shù)據(jù)等相關(guān)操作技巧,需要的朋友可以參考下2018-06-06基于jquery鼠標(biāo)點(diǎn)擊其它地方隱藏層的實(shí)例代碼
基于jquery鼠標(biāo)點(diǎn)擊其它地方隱藏層的實(shí)例代碼,需要的朋友可以參考下。2011-01-01使用jquery.upload.js實(shí)現(xiàn)異步上傳示例代碼
這篇文章主要介紹了使用jquery.upload.js實(shí)現(xiàn)異步上傳的示例代碼,需要的朋友可以參考下2014-07-07