javascript - How does jQuery implement off() to remove events?
高洛峰
高洛峰 2017-06-12 09:27:06
0
2
1099

We know that each method of binding events in jQuery has its corresponding method of removing event binding, such as off() corresponding to on(), unbind() corresponding to bind(), die() corresponding to live() , I am very curious about how this unbundling of anonymous events is achieved. The source code of jQuery is too esoteric and hard to understand. Can any expert post a simplified version of the code to analyze the implementation principle?

高洛峰
高洛峰

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

reply all (2)
phpcn_u1582

I think to understand off processing, you must first understand the on operation. I read the source code of jquery2.x last year, and the event aspect is quite complicated.

I looked through my rough notes and found that the video explaining the incident did not mention anything about it that I had to watch.

About binding events, you can combine the on source code implementation and the jquery.event.add method:

My understanding is that jquery mainly sets cache data cache for elements. The cache stores events variables (event callback queue collection), which are stored in the form of "event": "callback function array" to add multiple times to a certain DOM. When an event occurs, the callback can be triggered, but what is actually bound to the native event is the traversal execution of the callback function array.

As for off, let’s take a look at the source code part of off first:

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

When you see the last sentence, you know that it actually calls thejQuery.event.removemethod.

remove method

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

Mainly perform operations such as deleting event key-value pairs from the events variable stored in the cache when the element is previously on.

If it is just$(xx).off('click'), then it is to directly traverse and delete the callback function group corresponding to the click event in events. If the off parameter also passes a specific callback function, then it is Traverse and compare the callback array and delete the corresponding callback function...

For the jquery source code, it is recommended to watch the video of Miaowei Classroom for the early basic part. For other information, you can watch Daniel's blog post at http://www.cnblogs.com/aaronj... or purchase similar books on jquery source code analysis.

The source code involves too many details, and I won’t be able to sort them out for a while = =, so I will express the general point... Please correct me if I have any misunderstandings~

    phpcn_u1582

    The following is the code of 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 ); } ); }
      Latest Downloads
      More>
      Web Effects
      Website Source Code
      Website Materials
      Front End Template
      About us Disclaimer Sitemap
      php.cn:Public welfare online PHP training,Help PHP learners grow quickly!