recherche

Maison  >  Questions et réponses  >  le corps du texte

javascript - Comment jQuery implémente-t-il off() pour supprimer des événements ?

Nous savons que chaque méthode de liaison d'un événement dans jQuery a sa méthode correspondante de suppression de la liaison d'événement. Par exemple, off() correspond à on(), unbind() correspond à bind() et die() correspond à live. (). Je suis très curieux de savoir comment ce type de dégroupage des événements anonymes est mis en œuvre. Le code source de jQuery est trop ésotérique et difficile à comprendre. Un expert peut-il publier une version simplifiée du code pour analyser le principe de mise en œuvre ?

高洛峰高洛峰2730 Il y a quelques jours1211

répondre à tous(2)je répondrai

  • phpcn_u1582

    phpcn_u15822017-06-12 09:29:06

    Je pense que pour comprendre le traitement off, il faut d'abord comprendre le fonctionnement on. J'ai lu le code source de jquery2.x l'année dernière, et l'aspect événementiel est assez compliqué.

    J'ai parcouru mes notes préliminaires et j'ai découvert que la vidéo expliquant l'incident ne mentionnait rien de ce que je devais regarder.

    À propos des événements de liaison, vous pouvez combiner l'implémentation du code source et la méthode jquery.event.add :

    Je crois comprendre que jquery définit principalement le cache de données du cache pour les éléments. Le cache stocke les variables d'événements (collection de files d'attente de rappel d'événements), qui sont stockées sous la forme d'"événement": "tableau de fonctions de rappel" à ajouter plusieurs fois à un certain DOM. . Lorsqu'un événement se produit, le rappel peut être déclenché, mais ce qui est en réalité lié à l'événement natif est l'exécution traversante du tableau de fonctions de rappel.

    En ce qui concerne off, jetons d'abord un coup d'œil à la partie code source de off :

    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 );
            });
        },

    Quand vous voyez la dernière phrase, vous savez qu'elle appelle en fait la méthode jQuery.event.remove.

    supprimer la méthode

    remove: function( elem, types, handler, selector, mappedTypes ) {
    
            var j, origCount, tmp,
                events, t, handleObj,
                special, handlers, type, namespaces, origType,
                elemData = data_priv.hasData( elem ) && data_priv.get( elem );
    
            if ( !elemData || !(events = elemData.events) ) {
                return;
            }
    
            // Once for each type.namespace in types; type may be omitted
            types = ( types || "" ).match( core_rnotwhite ) || [""];
            t = types.length;
            while ( t-- ) {
                tmp = rtypenamespace.exec( types[t] ) || [];
                type = origType = tmp[1];
                namespaces = ( tmp[2] || "" ).split( "." ).sort();
    
                // Unbind all events (on this namespace, if provided) for the element
                if ( !type ) {
                    for ( type in events ) {
                        jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
                    }
                    continue;
                }
    
                special = jQuery.event.special[ type ] || {};
                type = ( selector ? special.delegateType : special.bindType ) || type;
                handlers = events[ type ] || [];
                tmp = tmp[2] && new RegExp( "(^|\.)" + namespaces.join("\.(?:.*\.|)") + "(\.|$)" );
    
                // Remove matching events
                origCount = j = handlers.length;
                while ( j-- ) {
                    handleObj = handlers[ j ];
    
                    if ( ( mappedTypes || origType === handleObj.origType ) &&
                        ( !handler || handler.guid === handleObj.guid ) &&
                        ( !tmp || tmp.test( handleObj.namespace ) ) &&
                        ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
                        handlers.splice( j, 1 );
    
                        if ( handleObj.selector ) {
                            handlers.delegateCount--;
                        }
                        if ( special.remove ) {
                            special.remove.call( elem, handleObj );
                        }
                    }
                }
    
                // Remove generic event handler if we removed something and no more handlers exist
                // (avoids potential for endless recursion during removal of special event handlers)
                if ( origCount && !handlers.length ) {
                    if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
                        jQuery.removeEvent( elem, type, elemData.handle );
                    }
    
                    delete events[ type ];
                }
            }
    
            // Remove the expando if it's no longer used
            if ( jQuery.isEmptyObject( events ) ) {
                delete elemData.handle;
                data_priv.remove( elem, "events" );
            }
        },

    Effectuez principalement des opérations telles que la suppression des paires clé-valeur d'événement de la variable d'événements stockée dans le cache lorsque l'élément est précédemment activé.

    Si c'est juste $(xx).off('click'), alors il s'agit de parcourir et de supprimer directement le groupe de fonctions de rappel correspondant à l'événement de clic dans les événements. Si le paramètre off passe également une fonction de rappel spécifique, alors le tableau de rappel est parcouru et comparé, et le la fonction de rappel correspondante est supprimée…

    .

    Pour le code source de jquery, il est recommandé de regarder la vidéo de Miaowei Classroom pour la première partie de base. Pour d'autres informations, vous pouvez regarder le blog de Daniel sur http://www.cnblogs.com/aaronj... ou acheter. livres similaires sur l’analyse du code source jquery.

    Le code source implique trop de détails, et je ne pourrai pas les trier avant un moment = =, je vais donc exprimer le point général... Veuillez me corriger si j'ai des malentendus~

    répondre
    0
  • phpcn_u1582

    phpcn_u15822017-06-12 09:29:06

    Ce qui suit est le code de on

    function on( elem, types, selector, data, fn, 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 ) {
                on( elem, type, selector, data, types[ type ], one );
            }
            return elem;
        }
    
        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 elem;
        }
    
        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 elem.each( function() {
            jQuery.event.add( this, types, fn, data, selector );
        } );
    }

    répondre
    0
  • Annulerrépondre