DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> jQuery入門知識 >> JQuery特效代碼 >> 讀jQuery之十一 添加事件核心方法
讀jQuery之十一 添加事件核心方法
編輯:JQuery特效代碼     
這篇看看其源碼,這個add定義如下(省略大部分)
代碼如下:
add: function( elem, types, handler, data ) {
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}
...
}

定義了四個參數elem、types、handler和data分別為HTMLElement、事件類型(如click)、事件響應函數、數據。此外,types 可以以空格分開傳多種事件("mouseover mouseout")。handler 有時會是一個對象(實現live時)。data 最後會掛在擴充後的event對象上,即作為event的屬性。而event會在handler作為第一個參數拿到,這樣也就可以在handler拿到data了。
下面詳細說明
代碼如下:
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
return;
}

文本和注釋節點直接返回。
代碼如下:
if ( handler === false ) {
handler = returnFalse;
} else if ( !handler ) {
// Fixes bug #7229. Fix recommended by jdalton
return;
}

參數handler為false時,將handler賦值為returnFalse,returnFalse為一個函數,如下
代碼如下:
function returnFalse() {
return false;
}

jQuery通過handler為false來阻止元素默認行為,停止事件冒泡。這個需要結合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從字面上看是事件響應(回調)函數,但這裡出現handler.handler,讓人倍感怪異。即什麼時候會將handler當一個JS對象傳入呢?
多數時候傳的還是Function類型的,看看源碼中jQuery.event.add的調用可發現jQuery在實現live的時候會傳Object類型。如下
代碼如下:
add: function( handleObj ) {
jQuery.event.add( this,
liveConvert( handleObj.origType, handleObj.selector ),
jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
},

這時會把handleObjIn賦值為所傳的JS對象,真正的handler 卻是handleObjIn.handler。這話有點繞,慢慢體會。
代碼如下:
// Make sure that the function being executed has a unique ID
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}

所傳參數handler添加個屬性guid,為一個數字,自增的從1開始。即使用jQuery添加事件,會為事件響應函數默認的添加了屬性guid。這個guid再刪除事件時會用到。
代碼如下:
// Init the element's event structure
var elemData = jQuery._data( elem );

先取elemData,這裡使用了前面提到的jQuery._data。第一次為HTMLElement添加事件是elemData是個空對象({})。
代碼如下:
// 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。同樣第一次時這兩個變量都是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,刪除事件注冊時會將其置null,避免部分浏覽器中內存洩露。
代碼如下:
// Handle multiple events separated by a space
// jQuery(...).bind("mouseover mouseout", fn);
types = types.split(" ");

將字符串以空格為切割符轉成數組。這句使其可以一次添加多個事件,多個事件的handler是相同的。
後面是一個while循環
代碼如下:
while ( (type = types[ i++ ]) ) {
handleObj = handleObjIn ?
jQuery.extend({}, handleObjIn) :
{ handler: handler, data: data };
...
}

循環數組,裡面依次處理如下
, 取得handleObj
, 處理事件命名空間,以點號(.)來區別。如果type有點號,則具有命名空間,否則沒有
, 給handlerObj添加type,guid屬性。這些後續刪除事件時用到
, 取到handlers,special。多數情況下使用addEventListener/attachEvent來添加事件。從變量special可看出對於特殊的事件如ready,beforeunload及live事件是特殊處理的。 ready 調用的是jQuery.bindReady,而jQuery.bindReady內部調用的仍然是 addEventListener/attachEvent。beforeunload則是使用window.onbeforeunload來添加。live是實現事件代理的,他的處理也是特殊的。
, 最後吧handleObj添加到數組handles中。
jQuery.event.add 的最後一句,解決IE中內存洩露。
代碼如下:
// Nullify elem to prevent memory leaks in IE
elem = null;

jQuery事件管理的數據結構,我做了個圖。如下
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved