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

實例方法和便捷方法是指jQuery能夠直接經過連接操做的方法,是經過調用$.event上的方法(上一節介紹的底層方法)來實現的,經常使用的以下:html

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

     writer by:大沙漠 QQ:22969969jquery

  • 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>

渲染以下:app

和上一節同樣,咱們在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 contextmenuui

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

<!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>

效果和上面是同樣的。spa

 

源碼分析代理


實例方法是定義在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 ) {                                //若是沒有參數三、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上綁定的普通事件。

相關文章
相關標籤/搜索