徹底弄懂jQuery事件原理一

來源:互聯網
上載者:User

標籤:資料   string   部分   方法   而不是   源碼   執行   trigger   types   

jQuery為我們提供了一個非常豐富好用的事件API,相對於瀏覽器自身的事件介面,jQuery有以下特點:

1. 對瀏覽器進行了相容性處理,使用者使用不需要考慮瀏覽器安全色性問題

2. 事件數目據是保持在內部緩衝中的,而不是保持在DOM節點上

3. 事件委託機制,提供了一個非常簡單的事件委託使用方法

4. 自訂事件,不僅僅是瀏覽器事件,可以建立自訂事件

5. 協助工具功能,比如命名空間,事件數目據等等

那麼下面就來看看jQuery是怎麼實現的,首先掃一眼Event模組的源碼結構:

總共900行,總共包括5部分:

1. 正則和輔助函數:最上面的Regex和3個輔助函數,後面會說到

 

2. event輔助類:用於事件處理的輔助對象

 

3. Event可寫事件對象,等同於瀏覽器事件中的event對象,但Event對象的資料是可寫的,添加了jQuery的一些屬性。

 

4. 相容性處理:事件的相容性處理邏輯

 

5. 對外API,添加到jquery執行個體對象的對外API

這段代碼結構邏輯上分為4層,

第一層是對外API,這段是對使用者調用的參數處理

第二層是event輔助類,使用者調用以後會調用輔助類的各種方法

第三層是Event對象,event處理過程中會建立Event對象來代替瀏覽器事件中的event對象

第四層是相容性處理,針對瀏覽器中有些事件的相容性問題,進行了處理 

 

1. 我們從對外API開始說起,比如:

<div id=‘div_main‘>    <div id="div_sub"></div></div><script>    $("#div_main").on("click",function(){        console.log(1);    });
</script>

我們對$("#div_main")這個jquery對象調用了on方法,就可以註冊一個點擊事件,on方法是什嗎?見對外API那部分代碼

        on: function(types, selector, data, fn, /*INTERNAL*/ one) {            var origFn, type;            // Types can be a map of types/handlers            if (typeof types === "object") {                // ( types-Object, selector, data )                if (typeof selector !== "string") {                    // ( types-Object, data )                    data = data || selector;                    selector = undefined;                }                for (type in types) {                    this.on(type, selector, data, types[type], one);                }                return this;            }            if (data == null && fn == null) {                // ( types, fn )                fn = selector;                data = selector = undefined;            } else if (fn == null) {                if (typeof selector === "string") {                    // ( types, selector, fn )                    fn = data;                    data = undefined;                } else {                    // ( types, data, fn )                    fn = data;                    data = selector;                    selector = undefined;                }            }            if (fn === false) {                fn = returnFalse;            } else if (!fn) {                return this;            }            if (one === 1) {                origFn = fn;                fn = function(event) {                    // Can use an empty set, since event contains the info                    jQuery().off(event);                    return origFn.apply(this, arguments);                };                // Use same guid so caller can remove using origFn                fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);            }            return this.each(function() {                jQuery.event.add(this, types, fn, data, selector);            });        },

 這段代碼其實是對使用者調用的方法進行了各種參數情況邏輯判斷,最後歸根到jQuery.event.add方法,也就是最後是調用了event輔助類的方法,首先on方法對使用者傳入的參數進行了判斷,主要可能有以下幾種情況:

(1) 以json方式傳入多個事件方法,比如:

on({"click":fn1,"blur":fn2},"li",data);
on({"click":fn1,"blur":fn2},data);

        //json對象格式
        if (typeof types === "object") {
         //selector不是字串是資料,則重新設定資料變數,on({"click":fn1,"blur":fn2},data) if (typeof selector !== "string") { data = data || selector; selector = undefined; }
         //對每個json屬性遞迴調用on方法 for (type in types) { this.on(type, selector, data, types[type], one); } return this; }

(2)其他三種情況:on("click",fn) on("click","li",fn) on("click",data,fn)

            if (data == null && fn == null) {                // 類似on("click",fn1),重設變數                fn = selector;                data = selector = undefined;            } else if (fn == null) {                if (typeof selector === "string") {                    //類似on("click","li",fn)                     fn = data;                    data = undefined;                } else {                    //類似on("click",data,fn);                    fn = data;                    data = selector;                    selector = undefined;                }            }
       //捷徑,如果fn參數傳入false,自動化佈建為false方法 if (fn === false) { fn = returnFalse; } else if (!fn) { return this; }
            if (one === 1) {//只執行一次的方法,執行一次後刪除本事件對象                origFn = fn;                fn = function(event) {                    // Can use an empty set, since event contains the info                    jQuery().off(event);                    return origFn.apply(this, arguments);                };                // Use same guid so caller can remove using origFn                fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);            }            return this.each(function() {//對每個jquery執行個體進行調用                jQuery.event.add(this, types, fn, data, selector);            });

然後是one方法,其實就是調用上面的on方法,帶上one參數

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

off方法,和on方法類似,針對輸入參數的幾種情況最終是調用了event輔助類的remove方法。

 off: function(types, selector, fn) {            var handleObj, type;            if (types && types.preventDefault && types.handleObj) {                // ( event )  dispatched jQuery.Event                handleObj = types.handleObj;                jQuery(types.delegateTarget).off(                    handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,                    handleObj.selector,                    handleObj.handler                );                return this;            }            if (typeof types === "object") {                // ( types-object [, selector] )                for (type in types) {                    this.off(type, selector, types[type]);                }                return this;            }            if (selector === false || typeof selector === "function") {                // ( types [, fn] )                fn = selector;                selector = undefined;            }            if (fn === false) {                fn = returnFalse;            }            return this.each(function() {                jQuery.event.remove(this, types, fn, selector);            });        },

 

tigger方法,最終是調用event輔助類的tigger方法

        trigger: function(type, data) {            return this.each(function() {                jQuery.event.trigger(type, data, this);            });        },

triggerHandler方法,調用event類的方法

      triggerHandler: function(type, data) {            var elem = this[0];            if (elem) {                return jQuery.event.trigger(type, data, elem, true);            }        }

tiggerHandler和tigger方法的區別是,triggerHandler只執行jQuery對象數組中的第一個對象,並且不執行冒泡,不執行瀏覽器預設事件。

 

徹底弄懂jQuery事件原理一

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.