Heim > Artikel > Web-Frontend > jQuery-1.9.1 Quellcode-Analysereihe (10) Ereignisverpackung von Ereignissystem_jquery
Im vorherigen Artikel habe ich Ihnen die jQuery-1.9.1-Quellcode-Analyseserie (10) Ereignissystem-Ereignisarchitektur vorgestellt. 9.1 Quellcode-Analysereihe Weitere Informationen finden Sie unten.
Zunächst müssen Sie verstehen, dass die nativen Ereignisse des Browsers schreibgeschützt sind, was die Operationen von jQuery auf sie einschränkt. Ein einfaches Beispiel hilft Ihnen zu verstehen, warum jQuery ein neues Ereignisobjekt erstellen muss.
Bei der Delegationsverarbeitung beauftragt Knoten a Knoten b, die Fn-Funktion auszuführen, wenn auf a geklickt wird. Wenn das Ereignis zu Knoten b sprudelt, muss die Kontextumgebung bei der Ausführung von fn korrekt sein. Es ist Knoten a, der fn ausführt, nicht Knoten b. So stellen Sie sicher, dass der Kontext der Ausführung von fn Knoten a ist: Schauen Sie sich den Quellcode (roter Teil) an
//执行 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ).apply( matched.elem, args );
Verwenden Sie apply, um den Kontext der Ausführungsfunktion durch einen Knoten (matched.elem) zu ersetzen. Ein weiterer Punkt ist, dass args[0] das Ereignisobjektereignis ist. Wie kann sichergestellt werden, dass das Ereignis ein Ereignis von Knoten a ist? Dies ist die Funktion des wichtigen Attributs event.currentTarget, sodass vor der Ausführung von apply
ein Schritt erledigt istevent.currentTarget = matched.elem;
Ändern Sie direkt die currentTarget-Eigenschaft des Ereignisobjekts, was bei lokalen Browserereignissen nicht möglich ist. Aus diesem Grund haben wir das Ereignisobjekt von jQuery basierend auf lokalen Ereignissen erstellt.
Es gibt zwei Arten von Ereignissen: Mausereignisse und Tastaturereignisse (ich weiß nicht, wann Berührungsereignisse hinzugefügt werden können). Schauen Sie sich die detaillierten Eigenschaften dieser beiden
an
Einige davon sind browserspezifisch und keine W3C-Standards. jQuery unterteilt Ereigniseigenschaften in drei Teile
Eigenschaften, die von Maus- und Tastaturereignissen gemeinsam genutzt werden jQuery.event.props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" ")
Tastaturereignisspezifische Eigenschaften jQuery.event.keyHooks.props: "char charCode key keyCode".split(" ")
Mausereignisspezifische Eigenschaften jQuery.event.mouseHooks.props: "buttonbuttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")
a. Erstellen Sie ein neues Ereignisobjekt jQuery.event.fix(originalEvent)
Der Aufbau eines neuen Ereignisobjekts erfolgt in drei Schritten
Im ersten Schritt verwenden Sie event = new jQuery.Event(originalEvent), um ein neues Ereignisobjekt zu erstellen (wenn Sie die Rolle von new nicht verstehen, klicken Sie bitte hier) und fügen Sie isDefaultPrevented, originalEvent, type und hinzu timeStamp beim Erstellen des Ereignisses und die Markierung des Ereignisses wurde korrigiert (optimierte Verwendung, um unnötige Verarbeitung zu vermeiden). Der Quellcode von jQuery.Event(src, props) lautet wie folgt
jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } //src为事件对象 if ( src && src.type ) { this.originalEvent = src; this.type = src.type; //事件冒泡的文档可能被标记为阻止默认事件发生;这个函数可以反应是否阻止的标志的正确值 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; //src为事件类型 } else { this.type = src; } //将明确提供的特征添加到事件对象上 if ( props ) { jQuery.extend( this, props ); } //创建一个时间戳如果传入的事件不只一个 this.timeStamp = src && src.timeStamp || jQuery.now(); //标记事件已经修正过 this[ jQuery.expando ] = true; };
Das im ersten Schritt erstellte Ereignisobjekt
Der zweite Schritt besteht darin, zu ermitteln, um welche Art von Ereignis es sich bei dem aktuellen Ereignis handelt, und dann die entsprechenden Attribute nacheinander aus dem lokalen Ereignis originalEvent des Browsers zu kopieren
//创建可写的事件对象副本,并格式化一些特征名称 var i, prop, copy, type = event.type, originalEvent = event, fixHook = this.fixHooks[ type ]; if ( !fixHook ) { this.fixHooks[ type ] = fixHook = //rmouseEvent=/^(?:mouse|contextmenu)|click/ rmouseEvent.test( type ) ? this.mouseHooks : //rkeyEvent=/^key/ rkeyEvent.test( type ) ? this.keyHooks : {}; } //获得要从原生事件中拷贝过来的属性列表 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; ... //将原生的属性都拷贝到新的事件上 i = copy.length; while ( i-- ) { prop = copy[ i ]; event[ prop ] = originalEvent[ prop ]; }
Der dritte Schritt ist die Kompatibilitätsverarbeitung verwandter Attribute
// IE<9修正target特征值 if ( !event.target ) { event.target = originalEvent.srcElement || document; } // Chrome 23+, Safari?,Target特征值不能是文本节点 if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // IE<9,对于鼠标/键盘事件, 如果metaKey没有定义则设置metaKey==false event.metaKey = !!event.metaKey; //调用hooks的filter return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
Die letzte Codezeile führt eine kompatible Anpassungsverarbeitung für Mausereignisse und Tastaturereignisse durch.
fixHook.filter kann jQuery.event.keyHooks.filter sein
keyHooks.filter: function( event, original ) { //给键盘事件添加which特征值 if ( event.which == null ) { event.which = original.charCode != null ? original.charCode : original.keyCode; } return event; }
oder dieser jQuery.event.mouseHooks.filter
mouseHooks.filter: function( event, original ) { var body, eventDoc, doc, button = original.button, fromElement = original.fromElement; //如果事件pageX/Y特征不见了,用可用的clientX/Y来计算出来 if ( event.pageX == null && original.clientX != null ) { eventDoc = event.target.ownerDocument || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); } //如果必要的话添加relatedTarget特征 if ( !event.relatedTarget && fromElement ) { event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; } //添加点击事件which特征值: 1 === left; 2 === middle; 3 === right //备注:button不标准,因此不要是使用 if ( !event.which && button !== undefined ) { event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); } return event; }
Das zuletzt abgeschlossene Ereignisobjekt ist wie folgt (am Beispiel von Mausereignissen)
Originalereignisse werden in originalEvent gespeichert, Ziel speichert den Zielknoten (delegierter Knoten, Ereignisquelle) und andere Informationen werden übersprungen
b. Überlastungsereignismethode
Beim Erstellen eines neuen Ereignisobjekts event = new jQuery.Event(originalEvent) erbt das Ereignis die Methoden in jQuery.event.prototype. Werfen wir einen Blick auf die Methoden
Wir haben zuvor die Rolle der überladenen stopPropagation-Methode in jQuery.event.prototype analysiert: Zusätzlich zum Aufrufen der Methode des Ereignisobjekts, um Blasenbildung zu verhindern, gibt es auch eine Rolle, wenn auf dem delegierten Knoten mehrere delegierte Ereignisse auf die Verarbeitung warten. , verhindert eines der Ereignisse, die event.stopPropagation() aufrufen, die Ausführung der nachfolgenden Ereignisverarbeitung. Klicken Sie hier, um nach Schlüsselwörtern zum Anzeigen zu suchen
Einen ähnlichen Effekt hat auch die Funktion „preventDefault“. Dieser Code wurde zur Funktion „preventDefault“ hinzugefügt
this.isPropagationStopped = returnTrue;
在触发事件trigger函数和模拟冒泡simulate函数中都会根据isPropagationStopped()判断是否要执行DOM节点的默认操作。源码如下
isImmediatePropagationStopped是stopPropagation特殊用法,isImmediatePropagationStopped会直接阻止掉当前的处理和后面等待执行的事件处理,而stopPropagation会执行完当前的处理,然后阻止后面等待执行的事件处理。
源码如下
// jQuery.Event基于DOM事件所指定的ECMAScript语言绑定 // http://www.w.org/TR//WD-DOM-Level--Events-/ecma-script-binding.html jQuery.Event.prototype = { isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, preventDefault: function() { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( !e ) {return; } if ( e.preventDefault ) { e.preventDefault(); //IE支持 } else { e.returnValue = false; } }, stopPropagation: function() { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( !e ) {return; } if ( e.stopPropagation ) { e.stopPropagation(); } // IE支持 e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); } }
以上就是本文给大家介绍的jQuery-1.9.1源码分析系列(十)事件系统之事件包装,希望大家喜欢。