jQuery 2.0.3 源碼分析 事件體系結構

那麼jQuery事件處理機制能幫咱們處理那些問題?html

  1. 毋容置疑首先要解決瀏覽器事件兼容問題
  2. 能夠在一個事件類型上添加多個事件處理函數,能夠一次添加多個事件類型的事件處理函數
  3. 提供了經常使用事件的便捷方法
  4. 支持自定義事件
  5. 擴展了組合事件
  6. 提供了統一的事件封裝、綁定、執行、銷燬機制
  7. ……

爲了更深刻的理解幕後的實現,因此先整理總體的結構思路,從1.7後就去除了live綁定,因此如今的整個事件的API數組

如圖:瀏覽器

image

 


jQuery的事件綁定有多個方法能夠調用,以click事件來舉例:緩存

  • click方法
  • bind方法
  • delegate方法
  • on方法
$('#foo').click(function(){ })

$('#foo').bind('click',function(){ })

$("foo").delegate("td", "click", function() { });

$("foo").on("click", "td", function() { });

以上四種綁定都能達到同同樣的效果,可是各自又有什麼區別,內部又是如何實現?函數

 


源碼分析源碼分析

 

click方式測試

jQuery.each( ("blur focus focusin focusout load resize scroll unload 
click
 dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {

        // Handle event binding
        jQuery.fn[ name ] = function( data, fn ) {
            return arguments.length > 0 ?
                this.on( name, null, data, fn ) :
                this.trigger( name );
        };
    });

源碼很簡單,合併15種事件統一增長到jQuery.fn上優化

內部調用this.on / this.triggerui

 

bind方式this

bind: function( types, data, fn ) {
    return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
    return this.off( types, null, fn );
},

一樣調用的this.on/this.off

 

delegate方式

delegate: function( selector, types, data, fn ) {
    return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
    // ( namespace ) or ( selector, types [, fn] )
    return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
}

一樣調用的this.on/this.off

 

one方式

one: function( types, selector, data, fn ) {
    return this.on( types, selector, data, fn, 1 );
},

仍是this.on

 

可見以上的接口只是修改了不一樣的傳遞參數,最後都交給on實現的

 


實現最簡單的事件委託

給父元素綁定事件,子元素也能響應


 

其實委託的原理都是同樣的,經過事件對象過濾出關聯目標的hack,作相對應的處理,那麼JQuery是如何實現的呢?

 


jQuery事件的流程圖

在綁定階段與執行階段

image

 

 


 

那麼JQuery爲了更好的對事件的支持內部又作了哪些額外的優化操做?

 

兼容性問題處理:

瀏覽器的事件兼容性是一個使人頭疼的問題。IE的event在是在全局的window下, 而mozilla的event是事件源參數傳入到回調函數中。還有不少的事件處理方式也同樣

JQuery提供了一個 event的兼容類方案

jQuery.event.fix 對遊覽器的差別性進行包裝處理

例如:

  1. 事件對象的獲取兼容,IE的event在是在全局的window,標準的是event是事件源參數傳入到回調函數中
  2. 目標對象的獲取兼容,IE中採用srcElement,標準是target
  3. relatedTarget只是對於mouseout、mouseover有用。在IE中分紅了to和from兩個Target變量,在mozilla中 沒有分開。爲了保證兼容,採用relatedTarget統一塊兒來
  4. event的座標位置兼容
  5. 等等

 

事件的存儲優化:

jQuery並無將事件處理函數直接綁定到DOM元素上,而是經過$.data存儲在緩存$.cahce上,這裏就是以前分析的貫穿整個體系的緩存系統了

聲明綁定的時候:

  • 首先爲DOM元素分配一個惟一ID,綁定的事件存儲在$.cahce[ 惟一ID ][ $.expand ][ 'events' ]上,而events是個鍵-值映射對象,鍵就是事件類型,對應的值就是由事件處理函數組成的數組,最後在DOM元素上綁定(addEventListener/ attachEvent)一個事件處理函數eventHandle,這個過程由 jQuery.event.add 實現。

執行綁定的時候:

  • 當事件觸發時eventHandle被執行,eventHandle再去$.cache中尋找曾經綁定的事件處理函數並執行,這個過程由 jQuery.event. trigger 和 jQuery.event.handle實現。
  • 事件的銷燬則由jQuery.event.remove 實現,remove對緩存$.cahce中存儲的事件數組進行銷燬,當緩存中的事件所有銷燬時,調用removeEventListener/ detachEvent銷燬綁定在DOM元素上的事件處理函數eventHandle。

 

事件處理器:

jQuery.event.handlers

針對事件委託和原生事件(例如"click")綁定 區分對待

事件委託從隊列頭部推入,而普通事件綁定從尾部推入,經過記錄delegateCount來劃分,委託(delegate)綁定和普通綁定。

 

其他一些兼容事件的Hooks

fixHooks,keyHooks,mouseHooks

 


總的來講對於JQuery的事件綁定

在綁定的時候作了包裝處理

在執行的時候有過濾器處理

 

下章就開始深刻on內部實現的分析了

相關文章
相關標籤/搜索