Comparación de React y Vue en un ejemplo práctico

El autor del material, cuya traducción publicamos hoy, dice que tiene que usar Vue en el trabajo y que ha estudiado bien este marco. Sin embargo, siempre tuvo curiosidad por saber cómo están las cosas en otros mundos, es decir, en el universo React.

Leyó la documentación, vio algunos videos de entrenamiento y, aunque todo esto le pareció muy útil, quería entender realmente cuál era la diferencia entre React y Vue. Para él, la búsqueda de diferencias entre los marcos no consistía en averiguar si admitían el modelo de objeto virtual del documento o cómo representaban exactamente las páginas. Quería que alguien le explicara las características del código, que le mostrara lo que estaba pasando en él. Esperaba encontrar un artículo dedicado a descubrir tales diferencias, después de haber leído que alguien que solo conocía Vue o React (o una persona completamente nueva en desarrollo web) podría comprender mejor las diferencias entre estos marcos.



Sin embargo, no pudo encontrar ese artículo. Este hecho lo llevó a comprender que él mismo tuvo que tomar ese artículo y escribir en el camino, entendiendo las similitudes y diferencias entre React y Vue. De hecho, aquí hay una descripción de su experimento en comparación con estos dos marcos.

Disposiciones generales



Vue o reaccionar?

Para el experimento, decidí crear un par de aplicaciones de tareas bastante estándar que permiten al usuario agregar elementos a la lista de tareas y eliminarlos de ella. Ambas aplicaciones se desarrollan utilizando create-react-app estándar ( create-react-app para React y vue-cli para Vue). CLI es, si alguien no lo sabe, una abreviatura que significa interfaz de línea de comando, es decir, una interfaz de línea de comando.

Ahora propongo ver la apariencia de las aplicaciones en cuestión aquí.


Aplicaciones creadas por Vue y React

Estos son los repositorios con el código para estas aplicaciones: Vue ToDo , React ToDo .

Se usa el mismo código CSS allí y allá, la única diferencia es dónde se encuentran exactamente los archivos correspondientes. Dado esto, echemos un vistazo a la estructura de los proyectos.


Estructura del proyecto usando Vue y React

Como puede ver, la estructura de estos dos proyectos es casi idéntica. La única diferencia importante es que la aplicación React tiene tres archivos CSS, mientras que la aplicación Vue no los tiene en absoluto. La razón de esto es que, cuando se usa create-react-app , los componentes React están equipados con los archivos CSS que lo acompañan, y Vue CLI usa un enfoque diferente cuando los estilos se declaran dentro de un archivo de componente específico.

Como resultado, tanto el enfoque uno como el otro nos permiten lograr el mismo objetivo, mientras que, si se desea, nada nos impide organizar estilos diferentes de Vue o React. De hecho, todo se reduce a las preferencias personales de la persona que crea el proyecto web. Por ejemplo, el tema de la estructuración de CSS se debate constantemente en las comunidades de desarrolladores. Ahora solo seguimos los enfoques CSS estándar establecidos en la CLI de los marcos en cuestión.

Sin embargo, antes de continuar, echemos un vistazo a cómo se ve un componente Vue y React típico.

Aquí está el código del componente Vue (en nuestro proyecto, está en el archivo 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> 

Aquí está el código para el componente React (archivo 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; 

Ahora es el momento de sumergirse en los detalles.

¿Cómo se realiza la modificación de datos?


El cambio de datos también se denomina "mutación de datos". Estamos hablando de los cambios realizados en los datos que almacena nuestra aplicación. Entonces, si necesitamos cambiar el nombre de cierta persona de "John" a "Mark", entonces estamos hablando de "mutación de datos". Es en el enfoque del cambio de datos donde reside la diferencia clave entre React y Vue. A saber, Vue crea un objeto de data en el que se encuentran los datos y cuyo contenido se puede cambiar libremente. React crea un objeto de state en el que se almacena el estado de la aplicación y, cuando se trabaja con él, se requiere un esfuerzo adicional para cambiar los datos. Sin embargo, en React todo está organizado de esta manera por una razón, hablaremos de ello a continuación y, para empezar, consideraremos los objetos mencionados anteriormente.

Así es como se ve el objeto de data utilizado por Vue.

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

Así es como se ve el objeto de state utilizado en React:

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

Como puede ver, en ambos casos describimos los mismos datos, están diseñados de manera diferente. Como resultado, podemos decir que la transferencia de los datos iniciales a los componentes en Vue y React se ve muy, muy similar. Pero, como ya se mencionó, los enfoques para cambiar los datos existentes en estos marcos difieren.

Supongamos que tenemos un elemento de datos como name: 'Sunil' . Luego asigné la propiedad de name mi propio nombre.

En Vue, puede acceder a estos datos utilizando la construcción this.name . Y aquí está cómo cambiarlos: this.name = 'John' . No sé exactamente cómo me sentiría si mi nombre realmente cambiara, pero en Vue funciona así.

En React, puede acceder a los mismos datos utilizando la construcción this.state.name . Pero cambiarlos escribiendo algo como this.state.name = 'John' no es posible, ya que React tiene restricciones que impiden dichos cambios de datos. Por lo tanto, en React, debe usar algo como this.setState({name: 'John'}) .

El resultado de dicha operación es el mismo que el obtenido después de realizar una operación más simple en Vue. Tienes que escribir más código en React, pero en Vue hay algo así como una versión especial de la función setState , que se llama cuando parece un simple cambio de datos. Por lo tanto, para resumir, React requiere el uso del setState con la descripción de los datos que deben cambiarse, y Vue asume que el desarrollador quisiera usar algo similar al cambiar los datos dentro del objeto de data .

Ahora preguntémonos por qué React está tan setState y por qué se necesita la función setState . Puede encontrar respuestas a estas preguntas de Revant Kumar : “Esto se debe a que React busca volver a ejecutar, tras un cambio de estado, ciertos ganchos del ciclo de vida, como componentWillReceiveProps , shouldComponentUpdate , componentWillUpdate , render , componentDidUpdate . Se entera de que el estado ha cambiado cuando llama a la función setState . Si tuviera que cambiar el estado directamente, React tendría que hacer mucho más trabajo para rastrear los cambios, determinar qué ganchos de ciclo de vida ejecutar, y así sucesivamente. Como resultado, React usa setState para hacer la vida setState ".

Ahora que hemos descubierto los cambios en los datos, hablemos sobre cómo, en ambas versiones de nuestra aplicación, agregar nuevos elementos a la lista de tareas pendientes.

Agregar nuevos elementos a la lista de tareas


▍Reaccionar


Aquí se explica cómo hacerlo en React.

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

Aquí el campo utilizado para la input datos ( input ) tiene el value atributo. Este atributo se actualiza automáticamente mediante el uso de un par de funciones interconectadas que forman lo que se llama enlace de datos bidireccional (si no ha oído hablar de esto antes, espere un poco, hablaremos de esto en la sección sobre cómo agregar elementos a la aplicación Vue). Creamos este tipo de comunicación bidireccional debido a la presencia de un onChange eventos onChange adicional adjunto al campo de input . Echemos un vistazo al código de este campo para que pueda comprender lo que está sucediendo aquí.

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

Se handleInput función handleInput cuando cambia el valor del campo de input . Esto lleva a actualizar el elemento todo , que está dentro del objeto de state , al establecerlo en el valor que está en el campo de input . Así es como se ve la función handleInput .

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

Ahora, cuando el usuario hace clic en el botón + en la página de la aplicación para agregar un nuevo registro a la lista, la función createNewToDoItem llama al método this.setState y le pasa una función. Esta función toma dos parámetros. El primero es la matriz de list completa del objeto de state , y el segundo es el elemento todo actualizado por la función handleInput . La función luego devuelve un nuevo objeto que contiene la matriz de list y agrega un nuevo elemento de todo al final de esta matriz. El trabajo con la lista se organiza utilizando el operador de spread (si no lo ha conocido antes, tenga en cuenta que esta es una de las nuevas características de ES6 y busque detalles al respecto).

Finalmente, se escribe una cadena vacía en todo , que actualiza automáticamente el value en el campo de input .

▍Vue


La siguiente construcción se utiliza para agregar un nuevo elemento a la lista de tareas en Vue.

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

En Vue, el campo de entrada tiene una directiva v-model . Le permite organizar el enlace de datos bidireccional. Eche un vistazo al código de este campo y hable sobre lo que está sucediendo aquí.

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

La directiva v-model vincula un campo a una clave que existe en un objeto de datos llamado toDoItem . Cuando se carga la página, se escribe una línea vacía en toDoItem , se ve como todo: '' .

Si ya hay algunos datos, algo como todo: 'add some text here' , entonces el mismo texto ingresará al campo de entrada, es decir, 'add some text here' . En cualquier caso, si volvemos al ejemplo con una cadena vacía, el texto que ingresamos en el campo caerá, debido al enlace de datos, en la propiedad de todo . Este es un enlace de datos bidireccional, es decir, ingresar datos nuevos en el campo conduce a la grabación de estos datos en el objeto de data , y actualizar los datos en el objeto conduce a la aparición de estos datos en el campo.

Ahora recuerde la función createNewToDoItem() , de la que hablamos anteriormente. Como puede ver, colocamos el contenido de todo en la matriz de la list y luego escribimos una cadena vacía en todo .

Eliminar elementos de una lista


▍Reaccionar


En React, esta operación se realiza así.

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

Mientras la función deleteItem está en el archivo ToDo.js , puede acceder a ella sin problemas desde ToDoItem.js , primero pasando esta función como una propiedad a <ToDoItem/> . Así es como se ve:

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

Aquí primero pasamos la función, que la pone a disposición de los componentes secundarios. Además, vinculamos this y pasamos el parámetro key . La función utiliza este parámetro para distinguir el elemento ToDoItem que se eliminará de otros elementos. Luego, dentro del componente ToDoItem , hacemos lo siguiente.

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

Todo lo que se necesita hacer para acceder a la función ubicada en el componente primario es usar la construcción this.props.deleteItem .

▍Vue


La eliminación de un elemento de la lista en Vue se hace así.

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

Vue requiere un enfoque ligeramente diferente para eliminar elementos que el que usamos en React. A saber, hay tres pasos a seguir.

En primer lugar, esto es lo que debe hacer en el elemento para el que necesita llamar a la función para eliminarlo.

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

Luego, debe crear la función de emit como método en el componente secundario (en este caso, en ToDoItem.vue ), que se ve así.

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

Además, puede notar que estamos agregando ToDoItem.vue dentro de ToDo.vue .

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

Esto es lo que se llama un detector de eventos personalizado. Responde para emit llamadas con la línea de delete . Si captura un evento similar, llama a la función onDeleteItem . Se encuentra dentro de ToDo.vue , y no en ToDoItem.vue . Esta función, como se mencionó anteriormente, simplemente filtra la matriz de todo ubicada en el objeto de data para eliminar el elemento en el que se hizo clic.

Además, vale la pena señalar que en el ejemplo que usa Vue, uno simplemente podría escribir el código relacionado con la función de emit dentro del @click . Puede verse así.

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

Esto reduciría el número de pasos necesarios para eliminar un elemento de la lista de tres a dos. Cómo proceder es una cuestión de preferencia del desarrollador.

Para resumir esta sección, podemos decir que en React, el acceso a las funciones descritas en los componentes principales se organiza a través de this.props (dado que los props pasan a los componentes secundarios, que es una técnica estándar que se puede encontrar literalmente en todas partes). En Vue, los componentes secundarios deben desencadenar eventos utilizando la función de emit , y estos eventos ya son manejados por el componente principal.

Trabajar con oyentes de eventos.


▍Reaccionar


En React, los oyentes de eventos para algo simple, como un evento de clic, son bastante simples. Aquí hay un ejemplo de cómo crear un controlador de eventos de click para un botón que crea un nuevo elemento de tarea pendiente.

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

Aquí todo está organizado de manera bastante simple, es muy similar al procesamiento de tales eventos usando JavaScript puro.

Cabe señalar que aquí, configurar escuchas de eventos para presionar teclas, por ejemplo, para Enter , lleva un poco más de tiempo que en Vue. Aquí necesita que el evento onKeyPress maneje de la siguiente manera. Aquí está el código para el campo de entrada.

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

La función handleKeyPress llama a la función createNewToDoItem cuando reconoce un createNewToDoItem en Enter . Se ve así.

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

▍Vue


Los controladores de eventos en Vue son muy fáciles de configurar. Es suficiente usar el símbolo @ y luego especificar el tipo de oyente que queremos usar.

Por ejemplo, para agregar un detector de eventos de clic, puede usar el siguiente código.

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

Tenga en cuenta que @click es la abreviatura de v-on:click . Los oyentes de eventos Vue son buenos para ser controlados muy finamente. Por ejemplo, adjuntar la construcción .once al oyente hará que el oyente se active solo una vez.

Hay muchas abreviaturas que simplifican la escritura de oyentes que responden a las pulsaciones de teclas en el teclado. En React, como hemos dicho, esto lleva más tiempo que en Vue. Aquí se hace de manera muy simple.

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

Pasar datos a componentes secundarios


▍Reaccionar


En React, las propiedades se pasan al componente secundario cuando se crea. Por ejemplo, así:

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

Aquí puede ver dos propiedades pasadas al componente ToDoItem . A partir de ahora, se puede acceder a ellos en el componente secundario a través de this.props .

Por ejemplo, para acceder a la propiedad item.todo , solo use la construcción this.props.item .

▍Vue


En Vue, las propiedades también se pasan a los componentes secundarios cuando se crean.

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

Después de eso, se pasan a la matriz de props del componente hijo, por ejemplo, usando la construcción props: [ 'todo' ] . Puede acceder a estas propiedades en componentes secundarios por nombre, en nuestro caso es el nombre 'todo' .

Pasar datos al componente padre


▍Reaccionar


En React, la función se pasa primero al componente secundario como una propiedad donde se llama al componente secundario. Entonces se planea llamar a esta función, por ejemplo, agregándola como un controlador onClick , o llamándola llamando a this.props.whateverTheFunctionIsCalled . Esto lleva a una llamada a la función ubicada en el componente principal. Este proceso se describe en la sección sobre la eliminación de elementos de la lista.

▍Vue


Cuando se usa Vue, en un componente secundario, es suficiente escribir una función que pase datos a la función primaria. Se escribe una función en el componente principal que escucha los eventos de transferencia de valor. Cuando ocurre un evento similar, tal función se llama. Al igual que con React, se puede encontrar una descripción de este proceso en la sección sobre cómo eliminar elementos de la lista.

Resumen


Hablamos sobre cómo agregar, eliminar y modificar datos en aplicaciones basadas en Vue y React, cómo transferir datos, en forma de propiedades, de componentes principales a secundarios y cómo enviar datos de componentes secundarios a principales. Creemos que después de analizar los ejemplos de similitudes y diferencias, Vue y React son visibles, como dicen, a simple vista.

Por supuesto, hay muchas otras pequeñas diferencias entre React y Vue, pero espero que lo que hemos cubierto aquí sirva como una buena base para comprender cómo funcionan estos marcos. Los marcos a menudo se analizan al elegir la plataforma adecuada para un nuevo proyecto. Esperamos que este material ayude a tomar esa decisión.

Estimados lectores! ¿Qué diferencias entre React y Vue, en su opinión, son las más importantes que afectan la elección de un marco particular, por ejemplo, como base para un determinado proyecto?

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


All Articles