Maison > interface Web > js tutoriel > Arrêtez d'utiliser les fonctions anonymes dans les accessoires !

Arrêtez d'utiliser les fonctions anonymes dans les accessoires !

Mary-Kate Olsen
Libérer: 2025-01-01 11:13:09
original
863 Les gens l'ont consulté

Quit Using Anonymous Functions in Props!

D'accord, le titre est un peu un appât à clics. Il y a des moments où vous devez utiliser des fonctions anonymes comme accessoires, mais elles le sont probablement beaucoup moins, merci. Mais d'abord, décrivons le problème.

Fonctions anonymes comme accessoires

Dans les bibliothèques de composants comme Svelte et React, les fonctions anonymes utilisées comme accessoires de composants sont devenues une sorte de référence paresseuse qui menace de gonflement à plus grande échelle.

Je vois tellement de développeurs faire ça :

<button onclick={() => handleSubmit()}>Submit</button>
Copier après la connexion
Copier après la connexion

Au lieu de ça :

<button onclick={handleSubmit}>Submit</button>
Copier après la connexion
Copier après la connexion

Chacun de ces blocs de code produira littéralement exactement le même résultat. La seule différence est qu'une fonction anonyme a été interposée dans le premier exemple, et elle ne fait qu'appeler une fonction nommée sans argument.

Voyez-vous pourquoi l'utilisation de l'approche anonyme pourrait être un problème ? Chaque fois que ce bouton est rendu, une toute nouvelle fonction anonyme est créée et conservée en mémoire. Si vous en avez dix rendus sur la même page, vous disposez de dix fonctions anonymes distinctes conservées en mémoire.

Maintenant, vous pourriez dire : "D'accord, mais à quelle fréquence vais-je avoir plus de, disons, dix ou vingt éléments interactifs sur une page ?" Et la réponse est : "Vous pensez peut-être qu'il s'agit d'un cas extrême, mais cela revient plus souvent que vous ne le pensez. Et autant être prêt pour l'avantage avec de bonnes habitudes !"

Un excellent exemple de cas où cela peut poser un problème concerne les tableaux ou listes plus grands dotés de fonctionnalités interactives, telles que la suppression ou la modification d'une ligne ou d'un élément. Si vous avez, par exemple, un composant de type grille de données sur votre page et que votre pagination est, disons, de 100 lignes par page, alors quelle que soit la fonction anonyme créée par chaque ligne, elle sera là 100 fois. Si vous avez une case à cocher qui fait quelque chose sur chaque ligne, ainsi que des boutons Modifier et Supprimer, vous disposez désormais de 300 fonctions anonymes conservées en mémoire, ainsi que des 3 fonctions d'origine nommées et déclarées, appelées par les fonctions anonymes.

C'est encore pire si vous faites des astuces comme le pré-rendu mais en cachant la page de données suivante par souci d'efficacité. Dans cet exemple, vous disposez désormais de 600 instances de fonctions anonymes en mémoire.

Ok, alors pourquoi les gens font ça ?

Je peux penser à au moins deux raisons pour lesquelles cette habitude est si répandue et enracinée.

Réactivité ou autre comportement souhaité

Au moins dans Svelte, il y a des moments où vous devez faire cela pour vous assurer que la fonction est appelée de manière réactive. Il peut y avoir d'autres types de situations qui nécessitent que vous fassiez cela pour que votre logique fonctionne comme prévu, et même si cela fait quelques années que je n'ai pas travaillé avec React, je parie qu'il existe également des exemples similaires dans cette bibliothèque.

Mais ce sont des cas extrêmes que vous pouvez résoudre selon vos besoins lors du codage.

Simplifier le passage des paramètres de fonction

Celui-ci est probablement le coupable le plus courant. Il vous permet de transmettre une sorte d'état directement dans la fonction, il est donc plus facile à comprendre et à utiliser lorsque vous apprenez pour la première fois une bibliothèque d'interface utilisateur comme Svelte ou React. C'est peut-être la raison pour laquelle la plupart des didacticiels présentent des fonctions anonymes comme accessoires.

Voici un exemple (dans Svelte 5) :

<button onclick={() => handleSubmit()}>Submit</button>
Copier après la connexion
Copier après la connexion

Beau et propre, non ? Mais nous avons ce problème de performances potentiel si nous avons des centaines d'instances de ce bouton sur cette page. Comment pouvons-nous refactoriser cela pour qu'il soit potentiellement plus performant ?

La solution la plus simple

Comme c'est souvent le cas en programmation, une solution simple et directe consiste à nous assurer que nous créons des composants individuels pour des choses comme EditButton, puis que le productId est limité à cette instance. Ainsi, nous n'avons rien à transmettre à notre fonction de gestionnaire car elle se trouve à l'intérieur d'un composant discret qui sait déjà quel est ce productId. C'est pourquoi il est généralement bon que le code soit plus modulaire que monolithique.

Vous devriez absolument essayer d'abord d'opter pour cette solution, si vous le pouvez. Et notez que, comme notre composant est isolé pour gérer un seul productId, nous n'avons tout simplement pas besoin de cette fonction anonyme. Au lieu de cela, notre fonction composant peut le gérer directement.

<button onclick={handleSubmit}>Submit</button>
Copier après la connexion
Copier après la connexion

La solution la plus complexe

Mais il y a des moments où nous ne pouvons pas confiner la logique de mise à jour à une échelle locale comme celle-ci en raison de l'architecture du système ou autre. Pour gérer ce genre de situation, nous faisons quelque chose qui est, oui, un peu plus complexe et, je déteste le dire, légèrement moins déclaratif que l'envoi d'une fonction anon comme accessoire. Mais il reste très lisible et fonctionne dans notre objectif de ne pas mettre en mémoire un tas de fonctions anonymes.

Cela implique d'utiliser des attributs de données sur l'élément html qui obtient l'événement que vous gérez (comme un clic). Et ça ressemble à ça :

// EditButton.svelte

<script>  
  // productId is sent to this component as a prop
  let { productId } = $props()
</script>

const onEditToggle = (productId) => {
  // Do some stuff with productId...
}

<button onclick={() => onEditToggle(productId)}>
  Edit
</button>
Copier après la connexion

Vous voyez ce qui se passe là-bas ? Nous plaçons l'ID du produit dans un attribut de données personnalisé sur l'élément de bouton HTML dans EditButton. Lorsque la fonction de gestionnaire se déclenche, elle peut récupérer l'ID du produit directement à partir de l'attribut de données de l'élément.

Maintenant, nous n'avons qu'une seule fonction, onEditToggle, déclarée en mémoire, et tout le reste y pointe simplement par référence.

L'équilibre entre lisibilité et performances

Mon sentiment personnel est de toujours commencer par un code si bien modularisé que la transmission des données clés se fait via des accessoires directement vers ce composant, plutôt que de laisser le composant être monolithique et devoir déterminer tout cela en interne. C'est ce que je décris ci-dessus dans "La solution la plus simple".

Si vous ne pouvez absolument pas faire cela, optez pour la deuxième solution avec des attributs de données.

Maintenant, vous pourriez affirmer que parce que l'utilisation des fonctions anon est un peu plus lisible que la gestion des attributs de données, c'est la meilleure chose à faire pour commencer, vous pourrez donc simplement l'adapter plus tard si vous rencontrez des problèmes de performances.

Je suis généralement d'accord avec cette ligne de pensée, mais c'est un cas dans lequel les complications liées à cette façon de procéder sont un peu assez courantes pour que nous procédions toujours de la même manière. De cette façon, vous n’avez pas à vous demander si/quand utiliser une approche plutôt qu’une autre. Ils fonctionnent tous les deux, et l'un d'eux ne nécessitera pas de refactorisation plus tard si vous constatez que vous rencontrez ces problèmes de performances.

Enfin, une mise en garde

Il est tout à fait possible que Svelte gère cela d'une manière ou d'une autre pendant la transpilation pour adoucir ces fonctions anonymes d'une manière ou d'une autre. Je ne suis pas assez expert sur le runtime ou le compilateur de Svelte pour en être sûr. Mais personnellement, je pense qu'il s'agit d'un modèle plus sûr qui s'applique à n'importe quelle bibliothèque JS que vous pourriez utiliser, et c'est donc simplement une meilleure habitude à adopter dès le départ.

Qu'en pensez-vous ? Avez-vous des contrepoints ? Ou peut-être peut-il donner un aperçu de ce qui se passe au niveau de l'exécution et de la compilation avec Svelte, ce qui pourrait changer mon opinion ? Faites-le moi savoir dans les commentaires !

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!

source:dev.to
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal