Fermer

avril 21, 2021

Comment nettoyer après vous-même Pourquoi c'est important de Vue React


Les fuites de mémoire peuvent ralentir ou même planter une application. Ils peuvent être créés par accident, en ne nettoyant pas après vous-même. Découvrez comment nettoyer les écouteurs d'événements dans les deux frameworks JavaScript très populaires Vue et React.

Je travaille avec de nombreux clients, des développeurs débutants aux développeurs seniors, mais de temps en temps, je constate qu'il manque quelque chose à leur code. Malheureusement, ils ne nettoient pas après eux-mêmes, et je ne parle pas de leur vaisselle. Je parle de nettoyer les écouteurs d’événements qui, s’ils sont laissés, pourraient provoquer des fuites de mémoire.

Dans les petites applications, il se peut même que ce ne soit pas visible. Dans les plus grands, cela peut causer divers problèmes comme une expérience lente et lente, ou même un crash. Par conséquent, cet article explique comment nous pouvons nettoyer après nous-mêmes dans les frameworks JavaScript très populaires – Vue et React.

Quelle est la cause du problème?

Commençons par un exemple simple. Imaginez une application avec une liste d'articles. Cette liste est remplacée par une liste de nouveaux éléments toutes les quelques secondes. Le code ci-dessous illustre le problème et vous permettra de le voir.

App component

Toutes les quelques secondes, la fonction createItems est appelée pour créer de nouveaux éléments, qui sont alors en boucle. index et id sont passés au composant Item comme accessoires.

Item component

The Item rend l'ID de l'élément actuel et l'index de l'élément actuel. De plus, lorsque le composant est créé, un écouteur d'événement click est ajouté pour déconnecter l'ID de l'élément et l'index .

Vue

App. vue

 < template > 
   < div   id  =  " app "  > [19659019] < Item   v-for  =  " (item, i) of items "   : index  =  "  i  "  : id  = "  item.id  "  : key  = "  item.id  "  />   
   </  div > 
 </  template > 

 < script [19659013]> 
 import  Item  from   "./ components / Item" ; 

 const   createItems   =   () [19659044] => 
  Array .  from  ( { length :   10  } ) .  map  ([19659013] ()   =>   ( {
    id :  Math .  random  () 
      .  toString  ( 36 ) 
      . [19659055] substr  ( 2   9 ) 
  } ) ) ; 

 export   default   {
  composants :   {
    Article
  } 
   données  ()   {
     return   {
      éléments :   createItems  () 
    } ; 
  } 
   créé  ()   {[19659103] setInterval   ( ()   =>   {
       this .  items  =   createItems  ( ]) ; 
    }   5000 ) ; 
  } 
} ; 
 </  script  > 

 < style > 
 </  style > 

Item.vue

 < template > 
   < div >  Élément {{id}} - {{index}}  </  div > 
 </  template > 
 < script > 
 export   default   {
  accessoires :   {
    index :  Numéro 
    id :  Chaîne
  } 
   créé  ()   {
    window .  addEventListener  ( "click"   ()   =>   {
      console .  log  ( ` $ { this .  id }   -  $ {  this .  index }   " ) ; 
    } ) ; 
  } 
} ; 
 </  script > 
 

React

App.js

 import  React   { useState  useEffect }   from   ' react '; 
 import  Item  from  ' ./ Item '; 

 const   createItems   =   ()   => 
  Array .  from  ( { length :   10  } ) .  map  ([19659013] ()   =>   ( {
    id :  Math .  random  () 
      .  toString  ( 36 ) 
      . [19659055] substr  ( 2   9 ) 
  } ) ) ; 

 function   App  ()   {
   const   [ items  setItems ]   =   useState  ([19659055] createItems  () ) ; 

   useEffect  ( ()   =>   {
     setInterval  ] ( ()   =>   {
       setItems  ( createItems  () ) ; 
     }   5000 ) ; 
  }   [] ) ; 

   return   ([19659276] < div className  =  'App' > [19659065] { éléments .  carte  ( ( élément  i )   =>   {[19659285] return   < Item id  =  { item .  id }  index  =  { i }  key  =  { item .  id }   / > ; 
      } [19659013]) } 
     < /  div > 
  ) ; 
} 

 export   default  App  ; 

Item.js

 import  React   { useEffect }   from   'react' ; 

 const [19659043] Élément   =  accessoires  =>   {
   const   { id  index }   =  props ; 

   useEffect  ( () [19659044] =>   {
     const   onClick   =   ()   =>   {
      console .  log  ( ` $ { id }   -  $ { index }   " ) ; 
    } ; 
    
    window .  addEventListener  ( 'click'  onClick ) ; 
  }   [ ] ) ; 
   return   (
     < div > 
      Élément  { id }   -   { index } 
     < /  div > 
  ) [19659013]; 
} ; 

 export   default  Item ; 

Maintenant, ouvrez les outils de développement et accédez à l'onglet Console . Actualisez le site Web et cliquez immédiatement n'importe où sur la page. Vous devriez voir 10 éléments déconnectés.

Cependant, attendez quelques secondes que les éléments changent et cliquez à nouveau. Êtes-vous surpris de voir 20 journaux, au lieu de 10, même si nous avons encore 10 éléments? La raison en est que les composants ont été recréés pour les nouveaux éléments, car ils ont des identifiants différents. Pour chaque élément, nous fournissons l'accessoire key qui est utilisé par Vue et React pour déterminer si un élément doit être mis à jour ou recréé.

Dans tous les cas, attendez un peu plus longtemps et cliquez à nouveau. À un moment donné, nous avons quelques centaines d'auditeurs, et la plupart d'entre eux sont pour des éléments qui n'existent plus. Heureusement, cela peut être facilement résolu.

La ​​solution

Nous devons nous assurer de nettoyer après nous-mêmes lorsqu'un composant est détruit. Mettez à jour votre code comme indiqué ci-dessous.

Vue

Dans Vue, nous pouvons écouter l'événement hook: beforeDestroy sur l'instance du composant, et passer un rappel qui supprimera l'écouteur d'événements.

 created  ()   {
    
     const   onClick   =   ()   =>   {
      console .  log  ( ` $ { this .  id }   -  $ {  this .  index }   " ) ; 
    } ; 
    
    window .  addEventListener  ( "click"  onClick ) ; 

    
     this .  $ on  ] ( "hook: beforeDestroy"   ()   => 
      window .  removeEventListener  ( "click"  onClick ) 
    ) ; 
  } 

Vous pouvez également définir le crochet de cycle de vie beforeDestroy sur l'instance de composant, mais vous devrez également déplacer le gestionnaire onClick vers methods .

 methods : [19659045] {
     onClick  ()   {
      console .  log  ( ` $ { this .  id }   -  $ {  this .  index }   ` ) ; 
    } 
  } 
   beforeDestroy  ()   {
    window .  removeEventListener  ( "click"   this .  onClick ) ; 
  }  , 
   créé  ()   {
    window .  addEventListener  ( "click"   this .  onClick ) ; 
  } 

React

Dans React, renvoyez simplement une fonction du hook useEffect et supprimez l'écouteur d'événements.

 useEffect  ( ()   => [19659045] {
     const   onClick   =   ()   =>   {
      console .  log  ( ` $ { id }   -  $ { index }   " ) ; 
    } ; 
    
    window .  addEventListener  ( 'click'  onClick ) ; 

     return   ()   =>   {
      window .  removeEventListener  ( 'click'  onClick ) ; 
    } ; 
  }  ,   [] ) ; 

Si vous cliquez n'importe où sur l'écran et vérifiez à nouveau la console, vous verrez qu'il n'y a que 10 journaux. La fuite de mémoire a été corrigée avec succès.

Conclusion

Cet exemple utilise un écouteur d'événements, mais le même problème peut se produire si vous oubliez de nettoyer après des bibliothèques tierces. Certaines bibliothèques peuvent créer leurs propres écouteurs d'événements et vous demander d'appeler explicitement une méthode de nettoyage.

J'espère que vous avez trouvé cet article utile et que vous vous assurerez désormais de toujours nettoyer après vous-même. Vous pouvez trouver le code complet dans ce référentiel GitHub: https://github.com/ThomasFindlay/cleanup-after-yourself .




Source link