jQuery 源碼分析(十七) 事件系統模塊 實例方法和便捷方法 詳解

来源:https://www.cnblogs.com/greatdesert/archive/2019/10/30/11679507.html
-Advertisement-
Play Games

實例方法和便捷方法是指jQuery可以直接通過鏈接操作的方法,是通過調用$.event上的方法(上一節介紹的底層方法)來實現的,常用的如下: on(types,selector,data,fn,one) ;為匹配元素集合中的每個元素綁定一個或多個類型的事件監聽函數 types ;事件類型字元串,多個 ...


實例方法和便捷方法是指jQuery可以直接通過鏈接操作的方法,是通過調用$.event上的方法(上一節介紹的底層方法)來實現的,常用的如下:

  • on(types,selector,data,fn,one)  ;為匹配元素集合中的每個元素綁定一個或多個類型的事件監聽函數
    • types          ;事件類型字元串,多個事件類型之間用空格隔開
    • selector      ;可選,是一個選擇器表達式字元串,用於綁定代理事件。
    • data            ;傳遞給事件監聽函數的自定義數據,可以是任何類型。
    • fn           ;待綁定的監聽函數
    • one                  ;該事件是否只執行一次,為方法.one()提供支持

     writer by:大沙漠 QQ:22969969

  • off(types,selector,fn)  ;移除匹配元素中每個元素上綁定的一個或多個類型的監聽函數,參數如下:
    • types               ;一個或多個以空格分隔的事件類型和可選的命名空間
    • selector           ;可選的選擇器表達式字元串,用於移除代理事件
    • fn                    ;待移除的監聽函數,可以設置為false,表示內部定義的只返回false的函數
  • off(types,selector,fn)   ;移除匹配元素中每個元素上綁定的一個或多個類型的監聽函數
    • types        ;一個或多個以空格分隔的事件類型和可選的命名空間
    • selector    ;可選的選擇器表達式字元串,用於移除代理事件
    • fn          ;待移除的監聽函數,可以設置為false
  • bind(types,data,fn)            ;綁定一個普通事件
  • trigger(type, data)                  執行每個匹配元素上綁定的監聽函數和預設行為,並模擬冒泡過程
  • one(types,selector,data,fn)    ;為匹配元素集合中的每個元素綁定最多執行一次的事件監聽函數
  • hover(fnOver, fnOut)              ;用於在匹配元素上綁定一個或兩個監聽函數,當滑鼠指針進入和離開時,綁定的監聽函數被執行

我們還是以上一節的實例為例,用實例方法改寫一下,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
    <style>div{width: 200px;padding-top:50px;height: 150px;background: #ced;}div button{margin:0 auto;display: block;}</style>
</head>
<body>
    <div>        
        <button id="button">按鈕1</button>    
    </div>
    <script>
        $("div").on('click',()=>console.log('div普通單擊事件'));
        $('div').on('click','button',()=>console.log('d1代理事件'))
    </script>
</body>
</html>

渲染如下:

和上一節一樣,我們在div上綁定了一個普通事件和代理事件,當點擊div時觸發普通事件,點擊按鈕時分別觸發普通事件和代理事件。

另外為了更方變使用事件,jQuery還定義了很多的便捷事件方法,可以直接在jQuery實例上調用,註意:便捷方法不能綁定代理事件,只能綁定普通事件,所有的便捷方法如下:

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

我們將上面的例子改寫一下,用便捷方法來實現,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
    <style>div{width: 200px;padding-top:50px;height: 150px;background: #ced;}div button{margin:0 auto;display: block;}</style>
</head>
<body>
    <div>        
        <button id="button">按鈕1</button>    
    </div>
    <script>
        $("div").click(()=>console.log('div普通單擊事件'));                //用便捷事件來實現
        $('div').on('click','button',()=>console.log('d1代理事件'))        //代理事件不能用便捷方法來操作,因此我們用實例方法來實現
    </script>
</body>
</html>

效果和上面是一樣的。

 

源碼分析


實例方法是定義在jQuery.fn上的,on主要對參數做一些判斷,以支持多種格式的調用方法,實現如下:

jQuery.fn.extend({

    on: function( types, selector, data, fn, /*INTERNAL*/ one ) {    //該方法主要是修正參數。為匹配元素集合中的每個元素綁定一個或多個類型的事件監聽函數。
        var origFn, type;

        // Types can be a map of types/handlers                            //如果types是對象時,即參數格式是.on(Object,selector,data,one)或.one(Object,data,one)則
        if ( typeof types === "object" ) {
            // ( types-Object, selector, data )
            if ( typeof selector !== "string" ) {
                // ( types-Object, data )
                data = selector;
                selector = undefined;
            }
            for ( type in types ) {                                            //遍歷參數types,遞歸調用方法.on(types,selector,data,fn,one)綁定事件。
                this.on( type, selector, data, types[ type ], one );
            }
            return this;
        }

        if ( data == null && fn == null ) {                                //如果沒有參數3、4,則認為格式是.on(types,fn)
            // ( types, fn )
            fn = selector;                                                    //把第二個參數修正為fn。
            data = selector = undefined;
        } else if ( fn == null ) {                                        //傳入了三個參數時
            if ( typeof selector === "string" ) {                            //如果第二個參數是字元串,則認為格式是:.on(types,selector,fn)    忽略參數data,並把第三個參數作為參數fn。
                // ( types, selector, fn )
                fn = data;
                data = undefined;
            } else {                                                        //否則則認為忽略參數selector,並把第而個參數作為參數data,並把第三個參數作為參數fn。格式是.on(types,data,fn)
                // ( types, data, fn )
                fn = data;
                data = selector;
                selector = undefined;
            }
        }
        if ( fn === false ) {                                            //如果參數fn是布爾值false,則把它修正為總返回false的函數returnFalse()。
            fn = returnFalse;
        } else if ( !fn ) {                                                //如果fn沒有值則直接返回。
            return this;
        }

        if ( one === 1 ) {                                                //當方法one()調用.on()時,該參數為1,就會把監聽函數fn重新封裝為一個只會執行一次的新監聽函數。
            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() {                                    //遍歷當前的this
            jQuery.event.add( this, types, fn, data, selector );            //調用add()綁定事件
        });    
    },    
    one: function( types, selector, data, fn ) {                        //為匹配元素集合中的每個元素綁定一個或多個類型的事件監聽函數,每個監聽函數在每個匹配元素上最多執行一次。該方法簡單的通過調用.on(types,selector,data,fn,one)來實現。
        return this.on.call( this, types, selector, data, fn, 1 );
    },
    /**/
})

對於便捷方法來說,他就是在$.fn上定義每一個屬性,值為一個函數,內部還是調用$.fn.on來實現添加事件的,如下:

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 ) {    //參數1是一個數組 參數2是個函數,其中name是值,比如blur、focus

    // Handle event binding
    jQuery.fn[ name ] = function( data, fn ) {            //初始化事件便捷方法,在jQuery.fn對象上添加元素,這樣jQuery實例就可以直接訪問了
        if ( fn == null ) {                                    //修正參數,如果只傳入一個參數,則把該參數視為fn參數,把data視為null
            fn = data;
            data = null;
        }

        return arguments.length > 0 ?                        //根據參數個數決定是綁定事件還是觸發事件
            this.on( name, null, data, fn ) :                     //如果參數個數大於1,則調用方法.on()綁定事件監聽函數
            this.trigger( name );                                 //如果沒有參數,則調用方法.trigger()觸發事件監聽函數和預設行為
    };

    if ( jQuery.attrFn ) {                                    //記錄事件便捷方法名,在調用jQuery.attr()讀取或設置HTML屬性時,如果屬性名與事件便捷方法名同名,則會改為調用同名的事件便捷方法a
        jQuery.attrFn[ name ] = true;
    }

    if ( rkeyEvent.test( name ) ) {
        jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
    }

    if ( rmouseEvent.test( name ) ) {
        jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
    }
});

可以看到,如果執行便捷方法時不傳遞參數將觸發該事件,例如:$('div').click()將會觸發在該div上綁定的普通事件。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 對象(object)是 JavaScript 最重要的數據結構。ES6 對它進行了重大升級,本章介紹數據結構本身的改變及語法應用細節。 ...
  • “JSX” JSX就是Javascript和XML結合的一種格式。是一個 JavaScript 的語法擴展。 React發明瞭JSX,利用HTML語法來創建虛擬DOM。當遇到<,JSX就當HTML解析,遇到{就當JavaScript解析。 JSX,是一個 JavaScript 的語法擴展。JSX 可 ...
  • vue,element列表大數據卡頓問題,vue列表渲染慢,element表格渲染慢,表格渲染慢(卡),表格全選卡 ...
  • 結論 3XX開頭的HTTP狀態碼都表示重定向的響應。 301、308是永久重定向;302、303、307是臨時重定向。 301、302是http 1.0的內容,303、307、308是http1.1的內容。 301和302本來在規範中是不允許重定向時改變請求method的(將POST改為GET),實 ...
  • 1. Safari 3D變換會忽略z index的層級 在Safari瀏覽器下(此Safari瀏覽器包括iOS的Safari,iPhone上的微信瀏覽器,以及Mac OS X系統的Safari瀏覽器),當我們使用3D transform變換的時候,如果祖先元素沒有overflow:hidden/sc ...
  • Link: "原文鏈接" 譯文開始: 對網站進行性能優化對一個最容易的方法就是把JS和CSS進行打包壓縮。但是當你需要調試這些壓縮文件中的代碼的時候,會發生什麼?可能會是一場噩夢。但是,不用害怕,即將有一個解決方案到來,它就是Source Maps。 source maps提供一種將壓縮文件中的代碼 ...
  • 元素拖拽 作者:一粒塵土 時間:2019 10 30 使用範圍:兩個元素位置交換,移動元素到指定位置 涉及函數 |屬性|解釋 |: |: | |draggable|是否允許元素進行拖拽| |dragstart|拖拽開始觸發的函數,可在此獲取元素| |dragover|在目標元素內進行拖動時觸發的函數 ...
  • 從今天開始,持續更新typescript入門教程系列.... 目前ts越來越火,主流的前端框架,好比 angular,vue 3 均是採用ts來編寫,所有很多公司的項目都是用 ts 來寫的,所有是時候認真學習 ts 了 ts來源於微軟公司,越是大的公司,越是大的項目,越是推薦使用ts來編碼,ts是j ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...