Maison > interface Web > js tutoriel > jQuery-1.9.1 Série d'analyses de code source (10) Emballage d'événements de l'événement System_jquery

jQuery-1.9.1 Série d'analyses de code source (10) Emballage d'événements de l'événement System_jquery

WBOY
Libérer: 2016-05-16 15:30:50
original
1250 Les gens l'ont consulté

Dans l'article précédent, je vous ai présenté l'architecture d'événements du système d'événements de la série d'analyses de code source jQuery-1.9.1 (10) Cet article continue de vous présenter les connaissances pertinentes de jquery1. 9.1 série d'analyses du code source Veuillez voir ci-dessous pour plus de détails.

Tout d'abord, vous devez comprendre que les événements natifs du navigateur sont en lecture seule, ce qui limite les opérations de jQuery sur ceux-ci. Un exemple simple vous aidera à comprendre pourquoi jQuery doit construire un nouvel objet événement.

Dans le traitement de la délégation, le nœud a délègue le nœud b pour exécuter la fonction fn lorsque l'on clique sur a. Lorsque l'événement se propage vers le nœud b, l'environnement contextuel doit être correct lors de l'exécution de fn. C'est le nœud a qui exécute fn, pas le nœud b. Comment s'assurer que le contexte d'exécution de fn est le nœud a : regardez le code source (partie rouge)

//执行
ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ).apply( matched.elem, args );

Copier après la connexion

Utilisez apply pour remplacer le contexte de la fonction d'exécution par un nœud (matched.elem). Un autre point est que args[0] est l'événement objet événement. Comment s'assurer que l'événement est un événement du nœud a ? C'est la fonction de l'attribut important event.currentTarget, donc une étape est effectuée avant d'exécuter apply

event.currentTarget = matched.elem;
Copier après la connexion

Modifiez directement la propriété currentTarget de l'objet événement, ce qui n'est pas possible dans les événements locaux du navigateur. C'est pourquoi l'objet événement de jQuery est construit sur la base d'événements locaux.

Il existe deux types d'événements : les événements de souris et les événements de clavier (je ne sais pas quand des événements tactiles peuvent être ajoutés). Jetez un œil aux propriétés détaillées de ces deux

 

Certains d'entre eux sont spécifiques au navigateur et non aux normes du W3C. jQuery divise les propriétés des événements en trois parties

Propriétés partagées par les événements de souris et de clavier jQuery.event.props : "bulles altKey annulables ctrlKey currentTarget eventPhase metaKey RelatedTarget shiftKey target timeStamp view which".split(" ")

Propriétés spécifiques aux événements de clavier jQuery.event.keyHooks.props : "char charCode key keyCode".split(" ")

Propriétés spécifiques aux événements de la souris jQuery.event.mouseHooks.props : "bouton boutons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")

a. Construire un nouvel objet événement jQuery.event.fix(originalEvent)

La construction d'un nouvel objet événementiel se déroule en trois étapes

Dans la première étape, utilisez event = new jQuery.Event(originalEvent) pour construire un nouvel objet événement (si vous ne comprenez pas le rôle de new, veuillez cliquer ici), et ajoutez isDefaultPrevented, originalEvent, tapez et timeStamp lors de la création de l'événement. Et l'événement a été corrigé (utilisation optimisée pour éviter des traitements inutiles). Le code source de jQuery.Event(src, props) est le suivant

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;
};
Copier après la connexion

L'objet événement construit dans la première étape

 

La deuxième étape consiste à identifier de quel type d'événement il s'agit, puis à copier les attributs correspondants un par un à partir de l'événement local originalEvent du navigateur

 //创建可写的事件对象副本,并格式化一些特征名称
  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 ];
  }
Copier après la connexion

La troisième étape est le traitement de compatibilité des attributs associés

 // IE<9修正target特征值
  if ( !event.target ) {
    event.target = originalEvent.srcElement || document;
  }
  // Chrome 23+, Safari&#63;,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 &#63; fixHook.filter( event, originalEvent ) : event;
Copier après la connexion

La dernière ligne de code effectue un traitement d'adaptation compatible pour les événements de souris et les événements de clavier.

fixHook.filter peut être jQuery.event.keyHooks.filter

keyHooks.filter: function( event, original ) {
  //给键盘事件添加which特征值
  if ( event.which == null ) {
    event.which = original.charCode != null &#63; original.charCode : original.keyCode;
  }
  return event;
}
Copier après la connexion

ou ce 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 &#63; original.toElement : fromElement;
  }
  //添加点击事件which特征值: 1 === left; 2 === middle; 3 === right
  //备注:button不标准,因此不要是使用
  if ( !event.which && button !== undefined ) {
    event.which = ( button & 1 &#63; 1 : ( button & 2 &#63; 3 : ( button & 4 &#63; 2 : 0 ) ) );
  }
  return event;
}
Copier après la connexion

Le dernier objet événement complété est le suivant (en prenant les événements de souris comme exemple)

 

Les événements d'origine sont enregistrés dans originalEvent, la cible enregistre le nœud cible (nœud délégué, source d'événement) et les autres informations sont ignorées

b. Méthode d'événement de surcharge

Lors de la construction d'un nouvel objet événement event = new jQuery.Event(originalEvent), l'événement héritera des méthodes de jQuery.event.prototype. Jetons un coup d'œil aux méthodes

 

Nous avons précédemment analysé le rôle de la méthode stopPropagation surchargée dans jQuery.event.prototype : en plus d'appeler la méthode de l'objet événement pour éviter le bouillonnement, il existe également un rôle lorsque le nœud délégué a plusieurs événements délégués en attente de traitement. , l'un des événements appelant event.stopPropagation() empêchera l'exécution du traitement événementiel ultérieur. Cliquez ici pour rechercher des mots-clés à afficher

La fonction PreventDefault a également un effet similaire. Ce code a été ajouté à la fonction PreventDefault

this.isPropagationStopped = returnTrue;
Copier après la connexion

在触发事件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();
  }
}
Copier après la connexion

以上就是本文给大家介绍的jQuery-1.9.1源码分析系列(十)事件系统之事件包装,希望大家喜欢。

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal