Comparaison de React et Vue sur un exemple pratique

L'auteur du matériel, dont nous publions la traduction aujourd'hui, dit qu'il doit utiliser Vue au travail et qu'il a bien étudié ce cadre. Cependant, il était toujours curieux de savoir comment les choses se passent sur d'autres mondes, à savoir dans l'univers React.

Il a lu la documentation, regardé quelques vidéos de formation, et bien que tout cela lui ait semblé très utile, il voulait vraiment comprendre quelle était la différence entre React et Vue. Pour lui, la recherche de différences entre les frameworks n'était pas de savoir s'ils supportaient le modèle objet virtuel du document, ni comment ils rendaient exactement les pages. Il voulait que quelqu'un lui explique les caractéristiques du code, lui montre ce qui s'y passait. Il espérait trouver un article dédié à la découverte de telles différences, après avoir lu que quelqu'un qui ne connaissait que Vue ou React (ou une personne complètement nouvelle dans le développement Web) pourrait mieux comprendre les différences entre ces cadres.



Cependant, il n'a pas pu trouver un tel article. Ce fait l'a amené à comprendre qu'il devait lui-même prendre un tel article et écrire en cours de route, en comprenant les similitudes et les différences entre React et Vue. En fait, voici une description de son expérience en comparaison de ces deux cadres.

Dispositions générales



Vue ou React?

Pour l'expérience, j'ai décidé de créer quelques applications de tâches assez standard qui permettent à l'utilisateur d'ajouter des éléments à la liste de tâches et de les supprimer de celle-ci. Les deux applications sont développées à l'aide de create-react-app standard ( create-react-app pour React et vue-cli pour Vue). CLI est, si quelqu'un ne le sait pas, une abréviation qui signifie Interface de ligne de commande, c'est-à-dire une interface de ligne de commande.

Maintenant, je propose d'examiner l'aspect des applications en question ici.


Applications créées par Vue et React

Voici les référentiels avec le code de ces applications: Vue ToDo , React ToDo .

Le même code CSS est utilisé ici et là, la seule différence est où se trouvent exactement les fichiers correspondants. Compte tenu de cela, examinons la structure des projets.


Structure de projet Ă  l'aide de Vue et React

Comme vous pouvez le voir, la structure de ces deux projets est presque identique. La seule différence majeure est que l'application React possède trois fichiers CSS, tandis que l'application Vue n'en a pas du tout. La raison en est que, lors de l'utilisation de create-react-app , les composants React sont équipés des fichiers CSS associés, et Vue CLI adopte une approche différente lorsque les styles sont déclarés dans un fichier de composant spécifique.

Par conséquent, l'une et l'autre approche nous permettent d'atteindre le même objectif, tandis que, si vous le souhaitez, rien ne nous empêche d'organiser les styles différemment de Vue ou React. En fait, tout se résume aux préférences personnelles de la personne qui crée le projet Web. Par exemple, le sujet de la structuration CSS est constamment discuté dans les communautés de développeurs. Maintenant, nous suivons simplement les approches CSS standard définies dans la CLI des frameworks en question.

Cependant, avant d'aller plus loin, examinons Ă  quoi ressemble un composant Vue et React typique.

Voici le code du composant Vue (dans notre projet, il se trouve dans le fichier ToDoItem.vue ).

 <template>   <div class="ToDoItem">       <p class="ToDoItem-Text">{{todo.text}}</p>       <div class="ToDoItem-Delete"            @click="deleteItem(todo)">-       </div>   </div> </template> <script>   export default {       name: "to-do-item",       props: ['todo'],       methods: {           deleteItem(todo) {               this.$emit('delete', todo)           }       }   } </script> <style>   .ToDoItem {       display: flex;       justify-content: center;       align-items: center;   }   .ToDoItem-Text {       width: 90%;       background-color: white;       border: 1px solid lightgrey;       box-shadow: 1px 1px 1px lightgrey;       padding: 12px;       margin-right: 10px;   }   .ToDoItem-Delete {       width: 20px;       padding: 5px;       height: 20px;       cursor: pointer;       background: #ff7373;       border-radius: 10px;       box-shadow: 1px 1px 1px #c70202;       color: white;       font-size: 18px;       margin-right: 5px;   }   .ToDoItem-Delete:hover {       box-shadow: none;       margin-top: 1px;       margin-left: 1px;   } </style> 

Voici le code du composant React (fichier ToDoItem.js ).

 import React, {Component} from 'react'; import './ToDoItem.css'; class ToDoItem extends Component {   render() {       return (           <div className="ToDoItem">               <p className="ToDoItem-Text">{this.props.item}</p>               <div className="ToDoItem-Delete" onClick={this.props.deleteItem}>-</div>           </div>       );   } } export default ToDoItem; 

Il est maintenant temps de plonger dans les détails.

Comment se fait la modification des données?


La modification des données est également appelée «mutation des données». Nous parlons des modifications apportées aux données que notre application stocke. Donc, si nous devons changer le nom d'une certaine personne de «John» à «Mark», alors nous parlons de «mutation des données». C'est dans l'approche du changement de données que réside la principale différence entre React et Vue. À savoir, Vue crée un objet de data dans lequel se trouvent les données, et dont le contenu peut être librement modifié. React crée un objet d' state dans lequel l'état de l'application est stocké et lorsque vous travaillez avec lui, un effort supplémentaire est nécessaire pour modifier les données. Cependant, dans React, tout est organisé de cette manière pour une raison, nous en parlerons ci-dessous, et pour commencer, nous considérerons les objets mentionnés ci-dessus.

Voici à quoi ressemble l'objet de data utilisé par Vue.

 data() {     return {         list: [             {               todo: 'clean the house'             },             {               todo: 'buy milk'             }         ],     } }, 

Voici à quoi ressemble l'objet d' state utilisé dans React:

 constructor(props) {       super(props);       this.state = {           list: [               {                   'todo': 'clean the house'               },               {                   'todo': 'buy milk'               }           ],       };   }; 

Comme vous pouvez le voir, dans les deux cas, nous décrivons les mêmes données, elles sont simplement conçues différemment. En conséquence, nous pouvons dire que le transfert des données initiales vers les composants de Vue et React semble très, très similaire. Mais, comme déjà mentionné, les approches pour modifier les données existantes dans ces cadres diffèrent.

Supposons que nous ayons un élément de données comme le name: 'Sunil' . Ensuite, j'ai attribué la propriété name mon propre nom.

Dans Vue, vous pouvez accéder à ces données à l'aide de la construction this.name . Et voici comment les changer: this.name = 'John' . Je ne sais pas exactement ce que je ressentirais si mon nom changeait vraiment, mais dans Vue, ça fonctionne comme ça.

Dans React, vous pouvez accéder aux mêmes données à l'aide de la construction this.state.name . Mais les changer en écrivant quelque chose comme this.state.name = 'John' n'est pas possible, car React a des restrictions qui empêchent ces changements de données. Par conséquent, dans React, vous devez utiliser quelque chose comme this.setState({name: 'John'}) .

Le résultat d'une telle opération est le même que celui obtenu après avoir effectué une opération plus simple dans Vue. Vous devez écrire plus de code dans React, mais dans Vue il y a quelque chose comme une version spéciale de la fonction setState , qui est appelée quand, semble-t-il, un simple changement de données. Par conséquent, pour résumer, React nécessite l'utilisation de la setState avec la description des données qui doivent être modifiées, et Vue fonctionne sur l'hypothèse que le développeur souhaite utiliser quelque chose de similaire en modifiant les données à l'intérieur de l'objet de data .

Demandons-nous maintenant pourquoi React est ainsi setState et pourquoi la fonction setState est nécessaire. Vous pouvez trouver des réponses à ces questions auprès de Revant Kumar : «C'est parce que React cherche à réexécuter, lors d'un changement d'état, certains crochets du cycle de vie, tels que componentWillReceiveProps , shouldComponentUpdate , componentWillUpdate , render , componentDidUpdate . Il apprend que l'état a changé lorsque vous appelez la fonction setState . Si vous deviez changer d'état directement, React devrait faire beaucoup plus de travail pour suivre les modifications, déterminer les points d'ancrage du cycle de vie à exécuter, etc. En conséquence, React utilise setState pour vous setState vie. »

Maintenant que nous avons compris les modifications apportées aux données, parlons de la façon, dans les deux versions de notre application, d'ajouter de nouveaux éléments à la liste des tâches.

Ajouter de nouveaux éléments à la liste des tâches


▍ Réagir


Voici comment procéder dans React.

 createNewToDoItem = () => {   this.setState( ({ list, todo }) => ({     list: [         ...list,       {         todo       }     ],     todo: ''   }) ); }; 

Ici, le champ utilisé pour la input données ( input ) a la value attribut. Cet attribut est mis à jour automatiquement grâce à l'utilisation d'une paire de fonctions interconnectées qui forment ce qu'on appelle la liaison de données bidirectionnelle (si vous n'en avez pas entendu parler auparavant - attendez un peu, nous en parlerons dans la section sur l'ajout d'éléments à l'application Vue). Nous créons ce type de communication bidirectionnelle en raison de la présence d'un onChange événement onChange supplémentaire attaché au champ de input . Jetons un coup d'œil au code de ce champ afin que vous puissiez comprendre ce qui se passe ici.

 <input type="text"      value={this.state.todo}      onChange={this.handleInput}/> 

La fonction handleInput appelée lorsque la valeur du champ d' input change. Cela conduit à mettre à jour l'élément todo , qui se trouve à l'intérieur de l'objet d' state , en le définissant sur la valeur qui se trouve dans le champ d' input . Voici à quoi ressemble la fonction handleInput .

 handleInput = e => { this.setState({   todo: e.target.value }); }; 

À présent, lorsque l'utilisateur clique sur le bouton + de la page d'application pour ajouter un nouvel enregistrement à la liste, la fonction createNewToDoItem appelle la méthode this.setState et lui transmet la fonction. Cette fonction prend deux paramètres. Le premier est le tableau de list entier de l'objet d' state et le second est l'élément todo mis à jour par la fonction handleInput . La fonction renvoie ensuite un nouvel objet qui contient l'ancien tableau de list et ajoute un nouvel élément todo à la fin de ce tableau. Le travail avec la liste est organisé à l'aide de l'opérateur d' spread (si vous ne l'avez pas déjà rencontré, sachez que c'est l'une des nouvelles fonctionnalités d'ES6 et recherchez les détails à ce sujet).

Enfin, une chaîne vide est écrite en todo , qui met automatiquement à jour la value dans le champ de input .

â–ŤVue


La construction suivante est utilisée pour ajouter un nouvel élément à la liste des tâches dans Vue.

 createNewToDoItem() {   this.list.push(       {           'todo': this.todo       }   );   this.todo = ''; } 

Dans Vue, le champ de saisie a une directive v-model . Il vous permet d'organiser la liaison de données bidirectionnelle. Jetez un œil au code de ce champ et parlez de ce qui se passe ici.

 <input type="text" v-model="todo"/> 

La directive v-model lie un champ à une clé qui existe dans un objet de données appelé toDoItem . Lorsque la page se charge, une ligne vide est écrite dans toDoItem , elle ressemble à todo: '' .

S'il y a déjà des données, quelque chose comme todo: 'add some text here' , alors le même texte entrera dans le champ de saisie, c'est-à-dire 'add some text here' . Dans tous les cas, si nous revenons à l'exemple avec une chaîne vide, le texte que nous entrons dans le champ tombera, en raison de la liaison de données, dans la propriété todo . Il s'agit d'une liaison de données bidirectionnelle, c'est-à-dire que la saisie de nouvelles données dans le champ entraîne l'enregistrement de ces données dans l'objet de data et la mise à jour des données dans l'objet entraîne l'apparition de ces données dans le champ.

createNewToDoItem() vous maintenant de la fonction createNewToDoItem() , dont nous avons parlé plus haut. Comme vous pouvez le voir, nous mettons le contenu de todo dans le tableau de list , puis écrivons une chaîne vide à todo .

Supprimer des éléments d'une liste


▍ Réagir


Dans React, cette opération est effectuée comme ceci.

 deleteItem = indexToDelete => {   this.setState(({ list }) => ({     list: list.filter((toDo, index) => index !== indexToDelete)   })); }; 

Pendant que la fonction deleteItem trouve dans le fichier ToDo.js , vous pouvez y accéder sans problème à partir de ToDoItem.js , en passant d'abord cette fonction en tant que propriété à <ToDoItem/> . Voici à quoi ça ressemble:

 <ToDoItem deleteItem={this.deleteItem.bind(this, key)}/> 

Ici, nous passons d'abord la fonction, qui la rend disponible aux composants enfants. De plus, nous lions this et passons le paramètre key . Ce paramètre est utilisé par la fonction pour distinguer l'élément ToDoItem à supprimer des autres éléments. Ensuite, à l'intérieur du composant ToDoItem , nous procédons comme suit.

 <div className="ToDoItem-Delete" onClick={this.props.deleteItem}>-</div> 

Tout ce qui doit être fait pour accéder à la fonction située dans le composant parent est d'utiliser la construction this.props.deleteItem .

â–ŤVue


La suppression d'un élément de liste dans Vue se fait comme ceci.

 onDeleteItem(todo){ this.list = this.list.filter(item => item !== todo); } 

Vue nécessite une approche légèrement différente pour supprimer des éléments que celle que nous avons utilisée dans React. À savoir, il y a trois étapes à suivre.

Tout d'abord, voici ce que vous devez faire dans l'élément pour lequel vous devez appeler la fonction pour la supprimer.

 <div class="ToDoItem-Delete" @click="deleteItem(todo)">-</div> 

Ensuite, vous devez créer la fonction ToDoItem.vue en tant que méthode dans le composant enfant (dans ce cas, dans ToDoItem.vue ), qui ressemble à ceci.

 deleteItem(todo) {   this.$emit('delete', todo) } 

De plus, vous remarquerez peut-ĂŞtre que nous ajoutons des ToDoItem.vue dans ToDo.vue .

 <ToDoItem v-for="todo in list"         :todo="todo"         @delete="onDeleteItem" // <-- this :)         :key="todo.id" /> 

C'est ce qu'on appelle un écouteur d'événement personnalisé. Il répond pour emit appels avec la ligne de delete . S'il capture un événement similaire, il appelle la fonction onDeleteItem . Il est situé à l'intérieur de ToDo.vue et non dans ToDoItem.vue . Cette fonction, comme mentionné ci-dessus, filtre simplement le tableau de todo situé dans l'objet de data afin de supprimer l'élément sur lequel vous avez cliqué.

De plus, il convient de noter que dans l'exemple utilisant Vue, on pourrait simplement écrire le code lié à la fonction @click . Cela peut ressembler à ça.

 <div class="ToDoItem-Delete" @click="$emit('delete', todo)">-</div> 

Cela réduirait le nombre d'étapes nécessaires pour supprimer un élément de liste de trois à deux. La façon de procéder est une question de préférence pour les développeurs.

Pour résumer cette section, nous pouvons dire que dans React, l'accès aux fonctions décrites dans les composants parents est organisé via this.props (étant donné que les props passés aux composants enfants, qui est une technique standard qui peut être trouvée littéralement partout). Dans Vue, les composants enfants doivent déclencher des événements à l'aide de la fonction emit , et ces événements sont déjà gérés par le composant parent.

Travailler avec des auditeurs d'événements


▍ Réagir


Dans React, les écouteurs d'événements pour quelque chose de simple, comme un événement de clic, sont assez simples. Voici un exemple de création d'un gestionnaire d'événements de click pour un bouton qui crée un nouvel élément de tâche.

 <div className="ToDo-Add" onClick={this.createNewToDoItem}>+</div> 

Tout est arrangé assez simplement ici, c'est très similaire au traitement de tels événements en utilisant du JavaScript pur.

Il convient de noter qu'ici, la configuration d'écouteurs d'événements pour appuyer sur des touches, par exemple, pour Enter , prend un peu plus de temps que dans Vue. Ici, vous devez onKeyPress événement onKeyPress comme suit. Voici le code du champ de saisie.

 <input type="text" onKeyPress={this.handleKeyPress}/> 

La fonction handleKeyPress appelle la fonction createNewToDoItem lorsqu'elle reconnaît un createNewToDoItem sur Enter . Cela ressemble à ceci.

 handleKeyPress = (e) => { if (e.key === 'Enter') { this.createNewToDoItem(); } }; 

â–ŤVue


Les gestionnaires d'événements dans Vue sont très faciles à configurer. Il suffit d'utiliser le symbole @ , puis de spécifier le type d'écouteur que nous voulons utiliser.

Par exemple, pour ajouter un écouteur d'événements Click, vous pouvez utiliser le code suivant.

 <div class="ToDo-Add" @click="createNewToDoItem()">+</div> 

Veuillez noter que @click est l'abréviation de v-on:click . Les auditeurs d'événements Vue sont doués pour être très finement contrôlés. Par exemple, attacher la construction .once à l'écouteur ne déclenchera l'écouteur qu'une seule fois.

Il existe de nombreuses abréviations qui simplifient l'écriture des écouteurs qui répondent aux frappes sur le clavier. Dans React, comme nous l'avons dit, cela prend plus de temps que dans Vue. Ici, cela se fait très simplement.

 <input type="text" v-on:keyup.enter="createNewToDoItem"/> 

Passage de données aux composants enfants


▍ Réagir


Dans React, les propriétés sont transmises au composant enfant lors de sa création. Par exemple, comme ceci:

 <ToDoItem key={key} item={todo} /> 

Ici, vous pouvez voir deux propriétés transmises au composant ToDoItem . Désormais, ils sont accessibles dans le composant enfant via this.props .

Par exemple, pour accéder à la propriété item.todo , utilisez simplement la construction this.props.item .

â–ŤVue


Dans Vue, les propriétés sont également transmises aux composants enfants lors de leur création.

 <ToDoItem v-for="todo in list"           :todo="todo"           :key="todo.id"           @delete="onDeleteItem" /> 

Après cela, ils sont passés au tableau d' props du composant enfant, par exemple, en utilisant la construction props: [ 'todo' ] . Vous pouvez accéder à ces propriétés dans les composants enfants par leur nom, dans notre cas, c'est le nom 'todo' .

Passer des données au composant parent


▍ Réagir


Dans React, la fonction est d'abord transmise au composant enfant en tant que propriété où le composant enfant est appelé. Il est ensuite prévu d'appeler cette fonction, par exemple, en l'ajoutant en tant que gestionnaire onClick , ou en l'appelant en appelant this.props.whateverTheFunctionIsCalled . Cela conduit à un appel à la fonction située dans le composant parent. Ce processus est décrit dans la section sur la suppression d'éléments de la liste.

â–ŤVue


Lors de l'utilisation de Vue, dans un composant enfant, il suffit d'écrire une fonction qui transmet des données à la fonction parent. Une fonction est écrite dans le composant parent qui écoute les événements de transfert de valeur. Lorsqu'un événement similaire se produit, une telle fonction est appelée. Comme avec React, une description de ce processus peut être trouvée dans la section sur la suppression des éléments de la liste.

Résumé


Nous avons expliqué comment ajouter, supprimer et modifier des données dans les applications basées sur Vue et React, comment transférer des données, sous forme de propriétés, des composants parents vers les enfants et comment envoyer des données des composants enfants aux parents. Nous pensons qu'après avoir analysé les exemples de similitudes et de différences, Vue et React sont visibles, comme on dit, à l'œil nu.

Il y a, bien sûr, de nombreuses autres petites différences entre React et Vue, mais j'espère que ce que nous avons couvert ici servira de bonne base pour comprendre comment ces cadres fonctionnent. Les cadres sont souvent analysés lors du choix de la bonne plateforme pour un nouveau projet. Nous espérons que ce matériel vous aidera à faire un tel choix.

Chers lecteurs! À votre avis, quelles différences entre React et Vue sont les plus importantes qui affectent le choix d'un cadre particulier, par exemple, comme base d'un certain projet?

Source: https://habr.com/ru/post/fr419373/


All Articles