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 ReactEstos 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 ReactComo 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) , ], }; };
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?
