jQuery学习-事件之绑定事件(一)

本文详细阐述了jQuery实现事件绑定的核心原理,包括事件缓存系统、事件处理函数的创建与执行过程,以及如何实现事件的多次绑定与解绑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      我们都知道jQuery的事件其思想来源于Dean Edwards的addEvent,通过源码我们知道jQuery在为元素绑定事件时,每种类型的事件(click,blur)时只绑定了一次对应类型的事件处理方法,实际的方法是存在jQuery的缓存系统中的,这样做的好处我就不多说了,绑定方法的函数为add方法,在执行事件的时,通过handers在缓存系统中获取事件列表,然后通过dispatch函数来执行对应的事件。

jQuery.event = {

 

     add:  function( elem, types, handler, data, selector ) {
                 var tmp, events, t, handleObjIn,
            special, eventHandle, handleObj,
            handlers, type, namespaces, origType,
            elemData = jQuery._data( elem ); // 从缓存系统中获取对应的事件数据

         //  如果不存在事件数据则直接退出
         if ( !elemData ) {
             return;
        }

         //  Caller can pass in an object of custom data in lieu of the handler
         if ( handler.handler ) {
            handleObjIn = handler;
            handler = handleObjIn.handler;
            selector = handleObjIn.selector;
        }

         //  为事件添加标识
         if ( !handler.guid ) {
            handler.guid = jQuery.guid++;
        }

         // 初始化事件对象数据
         if ( !(events = elemData.events) ) {
            events = elemData.events = {};
        }
                 // 每种事件类型只绑定一次事件(eventHanle)
         if ( !(eventHandle = elemData.handle) ) {
            eventHandle = elemData.handle =  function( e ) {
                 //  Discard the second event of a jQuery.event.trigger() and
                 //  when an event is called after a page has unloaded
                 return  typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
                 // 通过dispatch来触发事件的执行,eventHandle.elem来绑定当前元素,防止this指向错误(attachEvent中this会指向window的bug)
                    jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
                    undefined;
            };
             //  Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
            eventHandle.elem = elem;
        }

         // 多个事件的绑定
         //  Handle multiple events separated by a space
        types = ( types || "" ).match( rnotwhite ) || [ "" ];
        t = types.length;
         while ( t-- ) {
            tmp = rtypenamespace.exec( types[t] ) || [];
            type = origType = tmp[1];
            namespaces = ( tmp[2] || "" ).split( "." ).sort();

             //  There *must* be a type, no attaching namespace-only handlers
             if ( !type ) {
                 continue;
            }

             //  If event changes its type, use the special event handlers for the changed type
            special = jQuery.event.special[ type ] || {};

             //  If selector defined, determine special event api type, otherwise given type
            type = ( selector ? special.delegateType : special.bindType ) || type;

             //  Update special based on newly reset type
            special = jQuery.event.special[ type ] || {};

             // 将事件组合成一个事件对象
            handleObj = jQuery.extend({
                type: type,
                origType: origType,
                data: data,
                handler: handler,
                guid: handler.guid,
                selector: selector,
                needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
                namespace: namespaces.join(".")
            }, handleObjIn );

             // handlers对应事件类型的事件列表
             if ( !(handlers = events[ type ]) ) {
                handlers = events[ type ] = [];
                handlers.delegateCount = 0;

                 //  Only use addEventListener/attachEvent if the special events handler returns false
                 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) ===  false ) {
                     // 真正绑定事件的地方,只绑定eventHandle
                     if ( elem.addEventListener ) {
                        elem.addEventListener( type, eventHandle,  false );

                    }  else  if ( elem.attachEvent ) {
                        elem.attachEvent( "on" + type, eventHandle );
                    }
                }
            }
             // 特殊事件的处理
             if ( special.add ) {
                special.add.call( elem, handleObj );

                 if ( !handleObj.handler.guid ) {
                    handleObj.handler.guid = handler.guid;
                }
            }

             //  将事件加入事件列表中
             if ( selector ) {
                handlers.splice( handlers.delegateCount++, 0, handleObj );
            }  else {
                handlers.push( handleObj );
            }

             // 表示事件曾经使用过,用于事件优化
            jQuery.event.global[ type ] =  true;
        }

         //  防止ie内存溢出
        elem =  null;
     },
     remove:  function( elem, types, handler, selector, mappedTypes ) {
           // 为元素移除事件
     },
     trigger:  function( event, data, elem, onlyHandlers ) {
          // 执行事件
     },
     dispatch:  function( event ) {
          // 分配事件(在执行方法时执行)
     },
     handlers:  function( event, handlers ) {
          // 获取缓存系统中对应事件类型的事件列表
     }
}

// 其实我们为每种事件绑定的方式是这样的
//通过
dispatch来执行对应的事件
function ( e ) {
      //  Discard the second event of a jQuery.event.trigger() and
      //  when an event is called after a page has unloaded
      return  typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
          jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
      undefined;
}

      好了,jQuery的绑定函数原理先介绍到这里。下次继续!一天一点,滴水汇河!

转载于:https://www.cnblogs.com/urols-jiang/p/4305158.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值