Fermer

mars 3, 2021

Création d'un composant de réaction de mise au point externe et de gestionnaire de clic


À propos de l'auteur

Arihant Verma est un ingénieur logiciel basé en Inde. Il aime lire du code open source et aider les autres à le comprendre. C'est un fanatique des éditeurs de textes riches. Ses …
En savoir plus sur
Arihant

Dans cet article, nous allons voir comment créer un focus extérieur et un gestionnaire de clics avec React. Ce faisant, vous apprendrez à recréer un composant React open source ( react-foco ) à partir de zéro. Pour tirer le meilleur parti de cet article, vous aurez besoin d'une compréhension de base des classes JavaScript, de la délégation d'événements DOM et de React. À la fin de l'article, vous saurez comment utiliser les propriétés d'instance de classe JavaScript et la délégation d'événements pour créer un composant React qui vous aide à détecter un clic ou un focus en dehors de tout composant React.

Souvent, nous devons détecter quand un clic s'est produit en dehors d'un élément ou lorsque le focus s'est déplacé en dehors de celui-ci. Certains des exemples évidents de ce cas d'utilisation sont les menus déroulants, les listes déroulantes, les info-bulles et les popovers. Commençons le processus de création de cette fonctionnalité de détection.

La méthode DOM pour détecter l'extérieur Cliquez

Si on vous a demandé d'écrire du code pour détecter si un clic s'est produit à l'intérieur ou à l'extérieur d'un nœud DOM , Qu'est-ce que tu ferais? Il y a de fortes chances que vous utilisiez l'API DOM Node.contains . Voici comment MDN l'explique:

La méthode Node.contains () renvoie une valeur Boolean indiquant si un nœud est un descendant d'un nœud donné, c'est-à-dire le nœud lui-même, un de ses enfants directs ( childNodes ), l'un des enfants directs des enfants, etc.

Testons-le rapidement. Créons un élément pour lequel nous voulons détecter les clics extérieurs. Je lui ai attribué une classe click-text .

click inside and outside me
 const concernElement = document.querySelector (". Click-text");

document.addEventListener ("mousedown", (événement) => {
  if (concernElement.contains (event.target)) {
    console.log ("Cliqué à l'intérieur");
  } autre {
    console.log ("Cliqué à l'extérieur / ailleurs");
  }
}); 

Nous avons fait les choses suivantes:

  1. Nous avons sélectionné l'élément HTML avec la classe click-text .
  2. Placez un écouteur d'événement avec la souris sur le document et définir une fonction de rappel du gestionnaire d'événements.
  3. Dans la fonction de rappel, nous vérifions si l'élément concerné – pour lequel nous devons détecter le clic extérieur – contient l'élément (lui-même compris) qui a déclenché l'événement mousedown ( event.target ).

Si l'élément qui a déclenché l'événement mouse down est soit notre élément concerné, soit tout élément qui se trouve à l'intérieur de l'élément concerné, cela signifie que nous avons cliqué à l'intérieur de l'élément concerné. [19659021] Cliquons à l'intérieur et à l'extérieur de l'élément dans la boîte de code ci-dessous, et vérifions la console.

Emballage de la logique de détection basée sur la hiérarchie DOM dans un composant React

Excellent! Jusqu'à présent, nous avons vu comment utiliser l'API DOM Node.contains pour détecter un clic en dehors d'un élément. Nous pouvons envelopper cette logique dans un composant React. Nous pourrions nommer notre nouveau composant React OutsideClickHandler . Notre composant OutsideClickHandler fonctionnera comme ceci:

  {
    console.log ("Je suis appelé chaque fois qu'un clic se produit en dehors du composant 'AnyOtherReactComponent'")
  }}
>
  

OutsideClickHandler comprend deux accessoires:

  1. children
    Il peut s'agir de n'importe quel enfant React valide. Dans l'exemple ci-dessus, nous transmettons le composant AnyOtherReactComponent comme enfant de OutsideClickHandler .

  2. onOutsideClick
    Cette fonction sera appelée si une un clic se produit n'importe où en dehors du composant AnyOtherReactComponent .

Ça sonne bien jusqu'à présent? Commençons à construire notre composant OutsideClickHandler .

 import React de 'react';

La classe OutsideClickHandler étend React.Component {
  render () {
    retournez this.props.children;
  }
} 

Juste un composant de base de React. Jusqu'à présent, nous n'en faisons pas grand-chose. Nous renvoyons simplement les enfants au fur et à mesure qu'ils sont transmis à notre composant OutsideClickHandler . Emballons les children avec un élément div et y attacher une référence React.

 import React, {createRef} from 'react';

La classe OutsideClickHandler étend React.Component {
  wrapperRef = createRef ();

  render () {
    revenir (
      
{this.props.children}
) } }

Nous utiliserons cette ref pour accéder à l'objet nœud DOM associé à l'élément div . En utilisant cela, nous allons recréer la logique de détection extérieure que nous avons faite ci-dessus.

Attachons l'événement mousedown sur le document à l'intérieur de componentDidMount Méthode du cycle de vie de réaction, et nettoyons cet événement à l'intérieur componentWillUnmount Méthode de cycle de vie React.

 classe OutsideClickHandler étend React.Component {
  componentDidMount () {
    document
      .addEventListener ('mousedown', this.handleClickOutside);
  }

  componentWillUnmount () {
    document
      .removeEventListener ('mousedown', this.handleClickOutside);
  }

  handleClickOutside = (événement) => {
    // Ici, nous écrirons le même clic extérieur
    // logique de détection comme nous l'avons utilisé auparavant.
  }
} 

Maintenant, écrivons le code de détection dans la fonction de gestionnaire de handleClickOutside .

 La classe OutsideClickHandler étend React.Component {
  componentDidMount () {
    document
      .addEventListener ('mousedown', this.handleClickOutside);
  }

  componentWillUnmount () {
    document
      .removeEventListener ('mousedown', this.handleClickOutside);
  }

  handleClickOutside = (événement) => {
    si (
      this.wrapperRef.current &&
      ! this.wrapperRef.current.contains (event.target)
    ) {
      this.props.onOutsideClick ();
    }
  }
} 

La logique de la méthode handleClickOutside dit ce qui suit:

Si le nœud DOM sur lequel on a cliqué ( event.target ) n'était ni notre conteneur div ( ce .wrapperRef.current ) ni aucun nœud à l'intérieur (! this.wrapperRef.current.contains (event.target) ), nous appelons le prop onOutsideClick .

Cela devrait fonctionner de la même manière que la détection des clics extérieurs fonctionnait auparavant. Essayons de cliquer en dehors de l’élément de texte gris dans la zone de code ci-dessous et observons la console:

The Problem With DOM Hierarchy Based Outside Click Detection Logic

Mais il y a un problème. Notre composant React ne fonctionne pas si l'un de ses enfants est rendu dans un portail React.

Mais que sont les portails React?

«Les portails fournissent un moyen de première classe pour rendre les enfants dans un nœud DOM qui existe en dehors du Hiérarchie DOM du composant parent. »

Documents React pour les portails

 Image montrant que les enfants React rendus dans le portail React ne suivent pas la hiérarchie DOM descendante.
Les enfants React rendus dans le portail React ne le font pas. suivre la hiérarchie DOM descendante. ( Grand aperçu )

Dans l'image ci-dessus, vous pouvez voir que Tooltip React component est un enfant de Container React component, si nous inspectons le DOM, nous constatons que le nœud DOM Tooltip réside en fait dans une structure DOM complètement séparée, c'est-à-dire qu'il n'est pas à l'intérieur du nœud DOM Container.

Le problème est que dans notre logique de détection externe jusqu'à présent, nous supposons que les enfants de OutsideClickHandler sera ses descendants directs dans l'arborescence DOM. Ce qui n'est pas le cas pour les portails React. Si les enfants de notre composant sont rendus dans un portail React – c'est-à-dire qu'ils sont rendus dans un nœud DOM séparé qui est en dehors de la hiérarchie de notre container div dans lequel notre composant OutsideClickHandler rend son enfants – alors la logique Node.contains échoue.

Mais comment échouerait-elle? Si vous essayez de cliquer sur les enfants de notre composant OutsideClickHandler – qui effectue le rendu dans un nœud DOM séparé à l'aide des portails React – notre composant enregistrera un clic extérieur, ce qui ne devrait pas être le cas. Voyez par vous-même:

<img src = "https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/abe4349b-5655-428e-9a5a-6650bd93de16/6-creating-outside- focus-click-handler-react-component-800w.gif "width =" 800 "height =" 500 "alt =" Image GIF montrant que si un enfant React rendu dans le portail React est cliqué, OutsideClickHandler, qui utilise Node .contains l'enregistre à tort comme clic extérieur. « />
L'utilisation de Node.contains pour détecter le clic extérieur du composant React donne un résultat erroné pour les enfants rendus dans un portail React. ( Grand aperçu )

Essayez-le:

Même si le popover qui s'ouvre en cliquant sur le bouton, est un enfant du composant OutsideClickHandler il ne parvient pas à détecter qu'il n'est pas en dehors de celui-ci

Utilisation de la propriété d'instance de classe et de la délégation d'événements pour détecter l'extérieur Cliquez sur

Alors, quelle pourrait être la solution? comptez sur DOM pour nous dire si le clic se produit à l'extérieur n'importe où. Nous devrons faire quelque chose avec JavaScript en réécrivant la mise en œuvre de OutsideClickHandler .

Commençons par une ardoise vierge. Donc en ce moment OutsideClickHandler est une classe React vide.

Le point crucial pour détecter correctement les clics extérieurs est:

  1. Ne pas se fier à la structure DOM.
  2. Pour stocker l'état 'cliqué' quelque part dans le code JavaScript.

Pour cet événement, la délégation viendra à notre aide. Prenons un exemple du même exemple de bouton et de popover que nous avons vu ci-dessus dans le GIF ci-dessus.

Nous avons deux enfants de notre fonction OutsideClickHandler . Un bouton et un popover – qui est rendu dans un portail en dehors de la hiérarchie DOM de OutsideClickHandler en cliquant sur le bouton, comme ceci:

<img loading = "lazy" decoding = "async" importance = "low" width = "800" height = "483" srcset = "https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/ 344dbf88-fdf9-42bb-adb4-46f01eedd629 / a1a55a0e-2033-4e26-9019-dad3d5340071 / 2-creation-outside-focus-click-handler-react-component.png 400w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_800/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/a1a55a0e-2033-4e26- 9019-dad3d5340071 / 2-creation-outside-focus-click-handler-react-component.png 800w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1200/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/a1a55a0e-2033-4e26- 9019-dad3d5340071 / 2-creation-outside-focus-click-handler-react-component.png 1200w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1600/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/a1a55a0e-2033-4e26- 9019-dad3d5340071 / 2-creation-outside-focus-click-handler-react-component.png 1600w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_2000/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/a1a55a0e-2033-4e26- 9019-dad3d5340071 / 2-creation-outside-focus-click-handler-react-component.png 2000w "src =" https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https: //cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/a1a55a0e-2033-4e26-9019-dad3d5340071/2-creating-outside-focus-click-handler-react-component.png "tailles = "100vw" alt = "Diagramme montrant la hiérarchie du document le composant OutsideClickHandler React et ses enfants rendus dans le portail React. « />
Hiérarchie DOM du document le composant OutsideClickHandler React et ses enfants rendus dans le portail React. ( Grand aperçu )

Lorsque l'un de nos enfants est cliqué, nous définissons une variable clickCaptured sur true . Si vous cliquez sur quelque chose en dehors d'eux, la valeur de clickCaptured restera false .

Nous stockerons la valeur de clickCaptured dans:

  1. A propriété d'instance de classe, si vous utilisez un composant réactif de classe.
  2. Une référence, si vous utilisez un composant React fonctionnel.

Nous n'utilisons pas l'état React pour stocker la valeur de clickCaptured car nous ne rendons rien basé sur ces données clickCaptured . Le but de clickCaptured est éphémère et prend fin dès que nous avons détecté si le clic s'est produit à l'intérieur ou à l'extérieur.

Voyons dans l'image ci-dessous la logique de réglage clickCaptured :

 Diagramme montrant le réglage de la variable clickCaptured sur true lorsque l'utilisateur clique sur les enfants du composant OutsideClickHandler.
Lorsque l'un des enfants du composant OutsideClickHandler est cliqué, nous définissons clickCaptured sur true. ( Grand aperçu )

Chaque fois qu'un clic se produit n'importe où, il bouillonne dans React par défaut. Il atteindra éventuellement le document .

<img loading = "lazy" decoding = "async" importance = "low" width = "800" height = "347" srcset = "https: //res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/35d75325-af9e-4160-a667- f4857839dbeb / 4-creation-outside-focus-click-handler-react-component.png 400w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_800/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/35d75325-af9e-4160- a667-f4857839dbeb / 4-creation-outside-focus-click-handler-react-component.png 800w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1200/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/35d75325-af9e-4160- a667-f4857839dbeb / 4-creation-outside-focus-click-handler-react-component.png 1200w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1600/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/35d75325-af9e-4160- a667-f4857839dbeb / 4-creation-outside-focus-click-handler-react-component.png 1600w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_2000/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/35d75325-af9e-4160- a667-f4857839dbeb / 4-creation-outside-focus-click-handler-react-component.png 2000w "src =" https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https: //cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/35d75325-af9e-4160-a667-f4857839dbeb/4-creating-outside-focus-click-handler-react-component "tailles" "100vw" alt = "Diagramme montrant la valeur de la variable clickCaptured lorsque l'événement mousedown remonte jusqu'au document, pour les cas de clics intérieurs et extérieurs. « />
Valeur de la variable clickCaptured lors d'un événement mousedown bulles jusqu'au document, pour les cas de clic à l'intérieur et à l'extérieur. ( Grand aperçu )

Lorsque le clic atteint le document deux choses peuvent se produire:

  1. clickCaptured sera vrai, si les enfants où vous avez cliqué.
  2. clickCaptured sera faux, si vous avez cliqué n'importe où en dehors d'eux.

Dans l'écouteur d'événements du document, nous allons faire deux choses maintenant:

  1. Si clickCaptured est vrai, nous déclenchons un gestionnaire de clics externes que l'utilisateur de OutsideClickHandler aurait pu nous donner via un accessoire.
  2. Nous remettons clickCaptured à false afin que nous soyons prêts pour une autre détection de clic.
<img loading = "lazy" decoding = "async" importance = "low" width = "800" height = "411" srcset = "https: //res.cloudinary .com / indysigner / image / fetch / f_auto, q_auto / w_400 / https: //cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/8157d7f6-976d-43f0-9197-40f1bf28fdb ting-outside-focus-click-handler-react-component.png 400w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_800/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/8157d7f6-976d-43f0- 9197-40f1bf28fddb / 5-creation-outside-focus-click-handler-react-component.png 800w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1200/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/8157d7f6-976d-43f0- 9197-40f1bf28fddb / 5-creation-outside-focus-click-handler-react-component.png 1200w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_1600/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/8157d7f6-976d-43f0- 9197-40f1bf28fddb / 5-creation-outside-focus-click-handler-react-component.png 1600w,
https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_2000/https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/8157d7f6-976d-43f0- 9197-40f1bf28fddb / 5-creation-outside-focus-click-handler-react-component.png 2000w "src =" https://res.cloudinary.com/indysigner/image/fetch/f_auto,q_auto/w_400/https: //cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/8157d7f6-976d-43f0-9197-40f1bf28fddb/5-creating-outside-focus-click-handler-react-component.png "100vw" alt = "Diagramme montrant la détection d'un clic à l'intérieur ou à l'extérieur du composant React en vérifiant la valeur de clickCapture lorsque l'événement mousedown atteint le document. « />
Détection si le clic s'est produit à l'intérieur ou à l'extérieur de React composant en vérifiant la valeur de clickCapture lorsque l'événement mousedown atteint le document. ( Grand aperçu )

Traduisons ceci en code.

 import React de "react"

La classe OutsideClickHandler étend React.Component {
  clickCaptured = false;
  
  render () {
    if (typeof this.props.children === 'fonction') {
      retourne this.props.children (this.getProps ())
    }

    renvoie this.renderComponent ()
  }
} 

Nous avons les éléments suivants:

  1. définissez la valeur initiale de la propriété d'instance clickCaptured sur false .
  2. Dans la méthode render nous vérifier si enfants prop est une fonction. Si c'est le cas, nous l'appelons et lui passons tous les accessoires que nous voulons lui donner en appelant la méthode de classe getProps . Nous n'avons pas encore implémenté getProps .
  3. Si l'accessoire children n'est pas une fonction, nous appelons la méthode renderComponent . Implémentons cette méthode maintenant.
 la classe OutsideClickHandler étend React.Component {
  renderComponent () {
    retourner React.createElement (
      this.props.component || 'portée',
      this.getProps (),
      this.props.children
    )
  }
} 

Comme nous n'utilisons pas JSX, nous utilisons directement l'API createElement de React pour envelopper nos enfants dans this.props.component ou dans un span ]. this.props.component peut être un composant React ou n'importe quel nom de balise de l'élément HTML comme 'div', 'section', etc. Nous transmettons tous les accessoires que nous voulons passer à notre élément nouvellement créé en appelant la méthode de classe getProps comme deuxième argument.

Écrivons maintenant la méthode getProps :

 class OutsideClickHandler extend React.Component {
  getProps () {
    revenir {
      onMouseDown: this.innerClick,
      onTouchStart: this.innerClick
    };
  }
} 

Notre élément React nouvellement créé aura les accessoires suivants qui lui seront transmis: onMouseDown et onTouchStart pour les appareils tactiles. Leurs deux valeurs sont la méthode de classe innerClick .

 class OutsideClickHandler extend React.Component {
  innerClick = () => {
    this.clickCaptured = true;
  }
} 

Si l'on clique sur notre nouveau composant React ou tout ce qu'il contient – qui pourrait être un portail React -, nous définissons la propriété d'occurrence de la classe clickCaptured sur true. Ajoutons maintenant les événements mousedown et touchstart au document, afin que nous puissions capturer l'événement qui bouillonne d'en bas.

 La classe OutsideClickHandler étend React.Component {
  componentDidMount () {
    document.addEventListener ('mousedown', this.documentClick);
    document.addEventListener ('touchstart', this.documentClick);
  }

  componentWillUnmount () {
    document.removeEventListener ('mousedown', this.documentClick);
    document.removeEventListener ('touchstart', this.documentClick);
  }

  documentClick = (événement) => {
    if (! this.clickCaptured && this.props.onClickOutside) {
      this.props.onClickOutside (événement);
    }
    this.clickCaptured = false;
  };
} 

Dans les gestionnaires d'événements mousedown et touchstart nous vérifions si clickCaptured est faux.

  1. clickCaptured serait vrai seulement si les enfants de notre composant React ont été cliqués.
  2. Si vous avez cliqué sur quelque chose d'autre clickCaptured serait false et nous ' Je sais qu'un clic extérieur s'est produit.

Si clickCaptured est faux, nous appellerons la méthode onClickOutside transmise dans un accessoire à notre composant OutsideClickHandler .

Voilà! Confirmons que si nous cliquons à l'intérieur du popover, il ne se ferme pas maintenant, comme c'était le cas auparavant:

 Image GIF montrant que si un enfant React rendu dans le portail React est cliqué, le composant OutsideClickHandler, qui utilise la délégation d'événements, s'enregistre correctement il s'agit d'un clic intérieur et non d'un clic extérieur.
L'utilisation de la logique de délégation d'événements détecte correctement le clic extérieur, même si les enfants sont rendus dans un portail React. ( Grand aperçu )

Essayons-le:

Merveilleux!

Détection de mise au point extérieure

Allons maintenant plus loin. Ajoutons également des fonctionnalités pour détecter lorsque le focus s'est déplacé en dehors d'un composant React. La mise en œuvre sera très similaire à celle que nous avons réalisée avec la détection des clics. Écrivons le code.

 la classe OutsideClickHandler étend React.Component {
  focusCaptured = false // 1. pour ajouter ceci

  innerFocus = () => {
    this.focusCaptured = vrai;
  }

componentDidMount () {
    document.addEventListener ('mousedown', this.documentClick);
    document.addEventListener ('touchstart', this.documentClick);
    document.addEventListener ('focusin', this.documentFocus);
  }

componentWillUnmount () {
    document.removeEventListener ('mousedown', this.documentClick);
    document.removeEventListener ('touchstart', this.documentClick);
    document.removeEventListener ('focusin', this.documentFocus);
  }

documentFocus = (événement) => {
    if (! this.focusCaptured && this.props.onFocusOutside) {
      this.props.onFocusOutside (événement);
    }
    this.focusCaptured = faux;
  };

// 2. pour indenter le morceau de code suivant
// 3. Ce morceau de code n'est pas copié dans le presse-papiers en cliquant sur le bouton "Copier"

getProps () {return {onMouseDown: this.innerClick, onTouchStart: this.innerClick, onFocus: this.innerFocus}; }

Tout est ajouté pour la plupart de la même manière, sauf une chose. Vous avez peut-être remarqué que bien que nous ajoutions un gestionnaire d'événements onFocus react sur nos enfants, nous définissons un écouteur d'événements focusin à notre document. Pourquoi pas un événement focus dites-vous? Parce que, 🥁🥁🥁, À partir de la v17, React mappe maintenant onFocus React event to focusin natif événement en interne.

In Si vous utilisez la version 16 ou antérieure, au lieu d'ajouter un gestionnaire d'événements focusin au document, vous devrez ajouter un événement focus en phase de capture à la place. Ce sera donc:

 document.addEventListener ('focus', this.documentFocus, true); 

Pourquoi en phase de capture vous pourriez demander? Car aussi étrange soit-il, l’événement de mise au point ne bouillonne pas .

Puisque j’utilise la v17 dans tous mes exemples, je vais continuer à utiliser le premier. Voyons ce que nous avons ici:

 Image GIF montrant la détection de correction du clic extérieur et de la mise au point par le composant React Foco, qui utilise la logique de détection de délégation d'événements.
Le composant React Foco détectant correctement le clic extérieur et la mise au point en utilisant la logique de détection de délégation d'événements . ( Grand aperçu )

Essayons-le nous-mêmes, essayez de cliquer à l'intérieur et à l'extérieur de l'arrière-plan rose. Utilisez également les touches Tab et Maj + Tab (dans Chrome, Firefox, Edge) ou Opt / Alt + Tab et Opt / Alt + Maj + Tab (dans Safari) pour basculer la mise au point entre le bouton interne et externe et voir comment l'état de la mise au point change. [19659125] Conclusion

Dans cet article, nous avons appris que le moyen le plus simple de détecter un clic en dehors d'un nœud DOM en JavaScript est d'utiliser Node.contains DOM API. J'ai expliqué l'importance de savoir pourquoi utiliser la même méthode pour détecter les clics en dehors d'un composant React ne fonctionne pas lorsque le composant React a des enfants qui s'affichent dans un portail React. En outre, vous savez maintenant comment utiliser une propriété d'instance de classe avec une délégation d'événement pour détecter correctement si un clic s'est produit en dehors d'un composant React, ainsi que comment étendre la même technique de détection à la détection de focus extérieur d'un composant React avec le focusin event caveat.

  1. React Foco Github Repository
  2. documentation mdn pour Node.contains DOM api
  3. Docs React pour les portails
  4. React createElement API
  5. React Github codebase Pull Request for mapping onFocus et onBlur méthodes pour utiliser en interne focusin et focusout événements natifs.
  6. Délégation d'événements Focus et Blur
 Smashing Editorial "width =" 35 " height = "46" loading = "lazy" decoding = "async (ks, vf, yk, il)




Source link