jQuery source code analysis event system module example method and convenient method details

Posted by techbinge on Wed, 30 Oct 2019 00:42:55 +0100

Instance method and convenient method refer to the method that jQuery can operate directly through link, which is realized by calling the method on $. event (the underlying method introduced in the previous section). The common methods are as follows:

  • on(types,selector,data,fn,one); bind one or more types of event listener functions to each element in the matching element collection
    • Types; event type string, multiple event types separated by spaces
    • Selector; optional, a selector expression string used to bind agent events.
    • Data; the user-defined data passed to the event listening function can be of any type.
    • fn; listening function to be bound
    • one; whether the event is only executed once, providing support for method. one().

    writer by: Desert QQ:22969969

  • off(types,selector,fn); remove one or more types of listening functions bound to each element in the matching element. The parameters are as follows:
    • Types; one or more space delimited event types and optional namespaces
    • Selector; optional selector expression string for removing agent events
    • fn; the listener function to be removed can be set to false, which means the internally defined function that only returns false.
  • off(types,selector,fn); removes one or more types of listening functions bound to each element in the matching element
    • Types; one or more space delimited event types and optional namespaces
    • Selector; optional selector expression string for removing agent events
    • fn; the listening function to be removed can be set to false
  • bind(types,data,fn); bind a common event
  • trigger(type, data), execute the listening function and default behavior bound on each matching element, and simulate the bubbling process
  • one(types,selector,data,fn); binding the event listener function to each element in the matched element collection to execute at most once
  • hover(fnOver, fnOut); used to bind one or two listening functions on matching elements. When the mouse pointer enters and leaves, the bound listening function is executed.

Let's take the example in the above section, and rewrite it with the example method as follows:

<!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">Button 1</button>    
    </div>
    <script>
        $("div").on('click',()=>console.log('div Normal click event'));
        $('div').on('click','button',()=>console.log('d1 Agency events'))
    </script>
</body>
</html>

Render as follows:

As in the previous section, we have bound a common event and a proxy event to the Div. when we click the div, we will trigger the common event, and when we click the button, we will trigger the common event and the proxy event respectively.

In addition, in order to change the use of events, jQuery also defines many convenient event methods, which can be called directly on the jQuery instance. Note: convenient methods cannot be bound to proxy events, but to ordinary events. All convenient methods are as follows:

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

Let's rewrite the above example and implement it in a convenient way, as follows:

<!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">Button 1</button>    
    </div>
    <script>
        $("div").click(()=>console.log('div Normal click event'));                //Using convenient events to achieve
        $('div').on('click','button',()=>console.log('d1 Agency events'))        //Agent events can't be operated by convenient methods, so we use instance methods to implement
    </script>
</body>
</html>

The effect is the same as above.

 

Source code analysis

The instance method is defined on jQuery.fn. On mainly makes some judgments on the parameters to support the call methods of various formats. The implementation is as follows:

jQuery.fn.extend({

    on: function( types, selector, data, fn, /*INTERNAL*/ one ) {    //This method mainly corrects the parameters. Bind one or more types of event listener functions to each element in the matching element collection.
        var origFn, type;

        // Types can be a map of types/handlers                            //If the type is an object, that is, if the parameter format is. on(Object,selector,data,one) or. one(Object,data,one), then
        if ( typeof types === "object" ) {
            // ( types-Object, selector, data )
            if ( typeof selector !== "string" ) {
                // ( types-Object, data )
                data = selector;
                selector = undefined;
            }
            for ( type in types ) {                                            //Ergodic parameter types,Recursive call method.on(types,selector,data,fn,one)Binding event.
                this.on( type, selector, data, types[ type ], one );
            }
            return this;
        }

        if ( data == null && fn == null ) {                                //If there are no parameters 3 and 4, the format is considered as.on(types,fn)
            // ( types, fn )
            fn = selector;                                                    //Amend the second parameter to fn. 
            data = selector = undefined;
        } else if ( fn == null ) {                                        //When three parameters are passed in
            if ( typeof selector === "string" ) {                            //If the second parameter is a string, the format is considered to be:.on(types,selector,fn)    Ignore parameters data,And take the third parameter as a parameter. fn. 
                // ( types, selector, fn )
                fn = data;
                data = undefined;
            } else {                                                        //Otherwise, the parameter is considered to be ignored. selector,And take the second parameter as the parameter. data,And take the third parameter as a parameter. fn. Format is.on(types,data,fn)
                // ( types, data, fn )
                fn = data;
                data = selector;
                selector = undefined;
            }
        }
        if ( fn === false ) {                                            //If parameters fn Boolean value false,Then amend it to always return false Function returnFalse(). 
            fn = returnFalse;
        } else if ( !fn ) {                                                //If fn No value is returned directly.
            return this;
        }

        if ( one === 1 ) {                                                //When method one()call.on()When the parameter is 1, the monitor function will be fn Repackaged as a new listener function that only executes once.
            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() {                                    //Traverse the current this
            jQuery.event.add( this, types, fn, data, selector );            //call add()Binding events
        });    
    },    
    one: function( types, selector, data, fn ) {                        //Bind one or more types of event listening functions to each element in the matching element collection, and each listening function can be executed at most once on each matching element. This method is simple by calling.on(types,selector,data,fn,one)To achieve.
        return this.on.call( this, types, selector, data, fn, 1 );
    },
    /*slightly*/
})

For the convenient method, it is to define every attribute on $. fn, whose value is a function, and internally call $. fn.on to add events, as follows:

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 ) {    //Parameter 1 is an array parameter 2 is a function where name It's a value, like blur,focus

    // Handle event binding
    jQuery.fn[ name ] = function( data, fn ) {            //An easy way to initialize events is to jQuery.fn Object, so jQuery The instance can be accessed directly
        if ( fn == null ) {                                    //Modify the parameter. If only one parameter is passed in, the parameter is regarded as fn Parameter data Regard as null
            fn = data;
            data = null;
        }

        return arguments.length > 0 ?                        //Decide whether to bind event or trigger event according to the number of parameters
            this.on( name, null, data, fn ) :                     //If the number of parameters is greater than 1, the method is called.on()Binding event listener
            this.trigger( name );                                 //If there are no parameters, call the method.trigger()Trigger event listener function and default behavior
    };

    if ( jQuery.attrFn ) {                                    //Record the event convenient method name in the jQuery.attr()Read or set HTML If the property name has the same name as the event convenience method name, the event convenience method with the same name will be called instead. 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;
    }
});

As you can see, if the convenience method is executed without passing parameters, the event will be triggered. For example: $('div').click() will trigger the normal event bound on the Div.

Topics: Javascript JQuery Attribute