Maison  >  Article  >  interface Web  >  Une analyse du système d'événements React

Une analyse du système d'événements React

不言
不言original
2018-07-23 11:17:281458parcourir

Le contenu partagé avec vous dans cet article concerne l'analyse du système d'événements React. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

1 Introduction

Il existe deux types de systèmes d'événements React : les événements synthétiques et les événements natifs.
Lors de l'écriture de composants React, il nous est facile de lier un événement synthétique, mais il n'existe aucun moyen de lier l'événement synthétique d'un autre composant dans un composant. Pour le moment, les événements natifs sont utiles.
En plus de parler d'événements mixtes (mélange d'événements synthétiques et d'événements natifs), le bouillonnement d'événements est également quelque chose que nous devons souvent traiter. Cet article le présentera en combinaison avec React.

Deuxième texte

1. Système d'événements React

1-1 React implémente une couche SyntheticEvent (événement synthétique) basée sur Virtual DOM, le gestionnaire d'événements que nous avons défini. de l'objet SyntheticEvent sera reçu, et le mécanisme de bouillonnement d'événements est également pris en charge. Nous pouvons utiliser stopPropagation() et PreventDefault() pour l'interrompre.

1-2. Tous les événements sont automatiquement liés à la couche la plus externe (document).

2. Mécanisme de liaison d'événements synthétiques

Au bas de React, deux choses principales sont effectuées pour les événements synthétiques : Délégation d'événements et liaison automatique.

2-1. Délégation d'événements Avant d'utiliser les événements
React, vous devez être familier avec son mécanisme de délégation d'événements. Il ne lie pas la fonction de traitement des événements directement au nœud réel, mais lie tous les événements à la couche la plus externe de la structure, en utilisant un écouteur d'événements unifié . Cet écouteur d'événements Une carte est maintenue pour stocker tous les écouteurs d'événements. et les gestionnaires au sein du composant. Lorsqu'un composant est monté ou démonté, certains objets sont simplement insérés ou supprimés sur cet écouteur d'événements unifié ; lorsqu'un événement se produit, il est d'abord traité par cet écouteur d'événements unifié, puis la véritable fonction de traitement des événements est trouvée dans le mappage et appelée. . Cela simplifie le mécanisme de traitement et de recyclage des événements et améliore considérablement l’efficacité.

2-2. Liaison automatique
Dans un composant React, le contexte de chaque méthode pointera vers l'instance du composant, c'est-à-dire la lie automatiquement au composant actuel . Et React mettra également en cache cette référence pour optimiser le processeur et la mémoire.

3. Utiliser des événements natifs dans React

Les événements natifs peuvent également être utilisés sous l'architecture React. React fournit une méthode de cycle de vie complète. ComponentDidMount sera appelé une fois le composant installé et que le vrai DOM existe dans le navigateur. À ce stade, nous pouvons terminer la liaison des événements natifs.
Mais React ne gère pas automatiquement les événements natifs, vous devez donc vous déconnecter des événements natifs lors de désinstallation du composant.

4. Mélanger les événements synthétiques avec les événements natifs

C'est mentionné dans le livre (pas trop d'introduction ici) :

  • Ne pas mélanger événements synthétiques avec mélange d'événements natifs

  • Évitez-le grâce au jugement e.target

Le point clé est le paragraphe suivant, qui est également le problème que nous voulons nous concentrer sur la résolution aujourd'hui :

Utiliser réagirEvent.nativeEvent.stopPropagation() pour empêcher les bulles ne fonctionnera pas. Le comportement consistant à empêcher les événements React de bouillonner ne peut être utilisé que dans le système d'événements synthétiques React, et il n'existe aucun moyen d'empêcher les événements natifs de bouillonner. Au contraire, empêcher le comportement de bouillonnement dans les événements natifs peut empêcher la propagation des événements synthétiques React.

5.React stopPropagation et stopImmediatePropagation

Mécanisme de bouillonnement d'événements :
Une analyse du système dévénements React

Événements liés via React, dans leurs fonctions de rappel L'objet événement est un SyntheticEvent synthétisé par React, ce qui n'est pas la même chose que l'événement DOM natif. Pour être précis, dans React, e.nativeEvent est l'événement de l'événement DOM natif.


Diagramme de séquence d'exécution d'événements synthétiques React et d'événements natifs :
Une analyse du système dévénements React

À partir du diagramme, nous pouvons tirer les conclusions suivantes :
(1) L'événement synthétique de DOM React ne sera déclenché que lorsque l'événement bouillonne dans le document, donc le e.stopPropagation de l'objet événement synthétique React ne peut qu'empêcher l'événement simulé React de bouillonner, mais ne peut pas empêcher le véritable événement DOM de bouillonner
( 2) DOM Empêcher la propagation des événements peut également empêcher les événements synthétiques. La raison en est que la prévention de la propagation des événements DOM empêche les événements de se propager au document
(3) Lorsque les événements synthétiques et les événements DOM sont liés au document, le traitement React. L'événement synthétique doit être placé en premier, il sera donc déclenché en premier. Dans ce cas, le stopImmediatePropagation de l'objet événement natif peut empêcher le déclenchement ultérieur de l'événement DOM du document

Une analyse du système dévénements React

stopImmediatePropagation : S'il existe plusieurs fonctions d'écoute d'événements du même type d'événement liées au même élément, lorsque des événements de ce type sont déclenchés, ils seront exécutés dans l'ordre dans lequel ils ont été ajoutés. Si l'une des fonctions d'écoute exécute la méthode event.stopImmediatePropagation(), les fonctions d'écoute restantes ne seront pas exécutées

6. React empêche le résumé de bouillonnement

(1) Pour éviter le bouillonnement entre les événements synthétiques, utilisez e.stopPropagation(); (2) pour empêcher les événements synthétiques d'être connectés au document le plus externe. évitez le bouillonnement entre les événements, utilisez e.nativeEvent.stopImmediatePropagation();
(3) pour empêcher le bouillonnement d'événements synthétiques et d'événements natifs, à l'exception du document le plus externe. Cela peut être évité en jugeant e.target. :

componentDidMount() { 
document.body.addEventListener('click', e => {   
 if (e.target && e.target.matches('p.code')) {  
      return;    
  }    
  this.setState({   active: false,    });   }); 
 }
7. Voir l'essence à travers le code source

7-1 Enregistrement d'événement

L'enregistrement d'événement consiste à convertir les événements React en événements natifs DOM au niveau du nœud de document et à s'inscrire rappels.

// enqueuePutListener 负责事件注册。
// inst:注册事件的 React 组件实例
// registrationName:React 事件,如:onClick、onChange
// listener:和事件绑定的 React 回调方法,如:handleClick、handleChange
// transaction:React 事务流,不懂没关系,不太影响对事件系统的理解
function enqueuePutListener(inst, registrationName, listener, transaction) {
    ... ...
   // doc 为找到的 document 节点
    var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
    // 事件注册
    listenTo(registrationName, doc);
    // 事件存储,之后会讲到,即存储事件回调方法
    transaction.getReactMountReady().enqueue(putListener, {
        inst: inst,
        registrationName: registrationName,
        listener: listener
    });
}
Examinons le code spécifique d'enregistrement des événements et comment lier les événements natifs DOM sur le document.

// 事件注册
// registrationName:React 事件名,如:onClick、onChange
// contentDocumentHandle:要将事件绑定到的 DOM 节点
listenTo: function (registrationName, contentDocumentHandle) {
    // document
    var mountAt = contentDocumentHandle;      
    // React 事件和绑定在根节点的 topEvent 的转化关系,如:onClick -> topClick
    var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName];
    
    for (var i = 0; i  Regardons le code spécifique pour lier les événements à la phase de bouillonnement : <p></p><pre class="brush:php;toolbar:false">// 三个参数为 topEvent、原生 DOM Event、Document(挂载节点)
trapBubbledEvent: function (topLevelType, handlerBaseName, element) {
    if (!element) {
        return null;
    }
    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));
}

// 三个参数为 Document(挂载节点)、原生 DOM Event、事件绑定函数
listen: function listen(target, eventType, callback) {
    // 去除浏览器兼容部分,留下核心后
    target.addEventListener(eventType, callback, false);
    // 返回一个解绑的函数
    return {
        remove: function remove() {
            target.removeEventListener(eventType, callback, false);
        }
    }
}
Dans la méthode d'écoute, nous avons finalement découvert la méthode native d'enregistrement d'événements addEventListener. Seul le nœud de document appellera cette méthode, donc seul le nœud de document a des événements DOM. Cela simplifie grandement la logique des événements DOM et économise de la mémoire.

7-2. Stockage de l'événement

Une fois l'événement enregistré, la fonction de rappel liée à l'événement doit être stockée. De cette façon, ce n'est qu'après le déclenchement de l'événement que nous pouvons trouver le rappel correspondant à déclencher. Dans le code initial, nous avons vu que la méthode putListener est utilisée pour stocker les rappels d'événements.

// inst:注册事件的 React 组件实例
// registrationName:React 事件,如:onClick、onChange
// listener:和事件绑定的 React 回调方法,如:handleClick、handleChange
putListener: function (inst, registrationName, listener) {
    // 核心代码如下
    // 生成每个组件实例唯一的标识符 key
    var key = getDictionaryKey(inst);
    // 获取某种 React 事件在回调存储银行中的对象
    var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});
    bankForRegistrationName[key] = listener;
}
7-3. Exécution de l'événement

  • Chaque fois qu'un événement est déclenché, le rappel enregistré par addEventListener sur le nœud racine sera exécuté, ce qui est le Méthode ReactEventListener.dispatchEvent, fonction d'entrée de distribution d'événements. La logique métier principale de cette fonction est la suivante :

    • Construire des événements synthétiques React basés sur des événements DOM.

    • Mettez l'événement de composition en file d'attente.

    • Événements dans la file d'attente des lots (y compris ceux qui n'ont pas été traités auparavant, premier entré, premier servi)

    • Trouvez le DOM et réagissez Composant déclenché par l'événement

    • À partir de ce composant React, appelez la méthode findParent pour parcourir tous les composants parents et les stocker dans un tableau.

    • De ce composant au dernier composant parent, selon le stockage d'événements précédent, utilisez le nom de l'événement React + la clé du composant pour trouver la méthode de rappel de liaison correspondante et exécutez-la. est :

Le bouillonnement des événements synthétiques React n'est pas vraiment un bouillonnement, mais la traversée de nœuds.

Trois post-scriptum

Je pense personnellement que stopImmediatePropagation est très utile. Il est nécessaire d'empêcher les événements synthétiques de remonter jusqu'au document DOM. La raison est :

1.合成事件本来就绑定在document上,完全可以获取这个document
2.stopImmediatePropagation可以阻止触发的document DOM上的事件,这十分有必要
3.不会阻止DOM 上的事件冒泡到document DOM
. Recommandations associées :

Trois méthodes de transmission de valeurs couramment utilisées dans Vue

Implémentation de l'enregistrement des événements React Event

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
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