javascript - Comment jQuery implémente-t-il off() pour supprimer des événements ?
高洛峰
高洛峰 2017-06-12 09:27:06
0
2
1312

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 ?

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

répondre à tous(2)
phpcn_u1582

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~

phpcn_u1582

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 );
    } );
}
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal