O autor do material, cuja tradução publicamos hoje, diz que precisa usar o Vue no trabalho e que estudou bem essa estrutura. No entanto, ele estava sempre curioso para descobrir como as coisas estão em outros mundos, a saber, no universo React.
Ele leu a documentação, assistiu a alguns vídeos de treinamento e, embora tudo isso lhe parecesse muito útil, ele queria realmente entender qual era a diferença entre React e Vue. Para ele, a busca por diferenças entre os frameworks não era descobrir se eles suportam o modelo de objeto virtual do documento ou como exatamente eles renderizam as páginas. Ele queria que alguém lhe explicasse as características do código, para mostrar o que estava acontecendo nele. Ele esperava encontrar um artigo dedicado a descobrir exatamente essas diferenças, depois de ler que alguém que conhecia apenas Vue ou React (ou uma pessoa completamente nova no desenvolvimento da Web) podia entender melhor as diferenças entre essas estruturas.

No entanto, ele não conseguiu encontrar esse artigo. Esse fato o levou a entender que ele próprio tinha que pegar esse artigo e escrever ao longo do caminho, entendendo as semelhanças e diferenças entre React e Vue. De fato, aqui está uma descrição de seu experimento em comparação com essas duas estruturas.
Disposições Gerais
Vue ou reagir?Para o experimento, decidi criar alguns aplicativos de tarefas bastante padrão, que permitem ao usuário adicionar itens à lista de tarefas e removê-los. Ambos os aplicativos são desenvolvidos usando
create-react-app
padrão (
create-react-app
para React e
vue-cli
para Vue). A CLI é, se alguém não souber, uma abreviação que significa Command Line Interface, ou seja, uma interface de linha de comando.
Agora, proponho olhar para a aparência dos aplicativos em questão aqui.
Aplicativos criados por Vue e ReactAqui estão os repositórios com o código para esses aplicativos:
Vue ToDo ,
React ToDo .
O mesmo código CSS é usado lá e ali, a única diferença é onde exatamente os arquivos correspondentes estão localizados. Diante disso, vamos dar uma olhada na estrutura dos projetos.
Estrutura do projeto usando Vue e reagirComo você pode ver, a estrutura desses dois projetos é quase idêntica. A única grande diferença é que o aplicativo React possui três arquivos CSS, enquanto o aplicativo Vue não os possui. O motivo disso é que, ao usar o
create-react-app
, os componentes do React são equipados com os arquivos CSS que o acompanham e o Vue CLI adota uma abordagem diferente quando os estilos são declarados dentro de um arquivo de componente específico.
Como resultado, tanto a abordagem como a outra nos permitem alcançar o mesmo objetivo, enquanto, se desejado, nada nos impede de organizar estilos de maneira diferente do Vue ou React. De fato, tudo se resume às preferências pessoais da pessoa que cria o projeto da web. Por exemplo, o tópico de estruturação de CSS está sendo constantemente discutido nas comunidades de desenvolvedores. Agora, apenas seguimos as abordagens CSS padrão estabelecidas na CLI dos frameworks em questão.
No entanto, antes de prosseguirmos, vejamos como é um componente típico do Vue e do React.
Aqui está o código do componente Vue (em nosso projeto, ele está no arquivo
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>
Aqui está o código para o componente React (arquivo
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;
Agora é hora de mergulhar nos detalhes.
Como é feita a modificação de dados?
Alterar dados também é chamado de "mutação de dados". Estamos falando de alterações feitas nos dados que nosso aplicativo armazena. Portanto, se precisarmos alterar o nome de uma determinada pessoa de "John" para "Mark", estaremos falando sobre "mutação de dados". É na abordagem da mudança de dados que reside a principal diferença entre React e Vue. Ou seja, o Vue cria um objeto de
data
no qual os dados estão localizados e seu conteúdo pode ser alterado livremente. React cria um objeto de
state
no qual o estado do aplicativo é armazenado e, ao trabalhar com ele, é necessário algum esforço adicional para alterar os dados. No entanto, no React, tudo é organizado dessa maneira por um motivo, falaremos sobre isso abaixo e, para começar, consideraremos os objetos mencionados acima.
É assim que o objeto de
data
usado pelo Vue se parece.
data() { return { list: [ { todo: 'clean the house' }, { todo: 'buy milk' } ], } },
Veja como é o objeto de
state
usado no React:
constructor(props) , ], }; };
Como você pode ver, nos dois casos, descrevemos os mesmos dados, eles são projetados de maneira diferente. Como resultado, podemos dizer que a transferência dos dados iniciais para os componentes no Vue e no React é muito, muito semelhante. Mas, como já mencionado, as abordagens para alterar os dados existentes nessas estruturas diferem.
Suponha que tenhamos um elemento de dados como o
name: 'Sunil'
. Em seguida, atribuí à propriedade
name
meu próprio nome.
No Vue, você pode acessar esses dados usando a construção
this.name
. E aqui está como alterá-los:
this.name = 'John'
. Não sei exatamente como me sentiria se meu nome realmente mudasse, mas no Vue funciona assim.
No React, você pode acessar os mesmos dados usando a construção
this.state.name
. Mas alterá-los escrevendo algo como
this.state.name = 'John'
não é possível, pois o React possui restrições que impedem essas alterações de dados. Portanto, no React, você deve usar algo como
this.setState({name: 'John'})
.
O resultado dessa operação é o mesmo que o obtido após a execução de uma operação mais simples no Vue. Você precisa escrever mais código no React, mas no Vue há algo como uma versão especial da função
setState
, chamada quando, ao que parece, uma simples alteração de dados. Portanto, para resumir, o React requer o uso do
setState
com a descrição dos dados que precisam ser alterados, e o Vue trabalha no pressuposto de que o desenvolvedor gostaria de usar algo semelhante alterando os dados dentro do objeto de
data
.
Agora vamos nos perguntar por que o React foi
setState
e por que a função
setState
é necessária. Você pode encontrar respostas para estas perguntas em
Revant Kumar : “Isso ocorre porque o React procura reexecutar, mediante uma alteração de estado, certos ganchos do ciclo de vida, como
componentWillReceiveProps
,
shouldComponentUpdate
,
componentWillUpdate
,
render
,
componentDidUpdate
. Ele descobre que o estado mudou quando você chama a função
setState
. Se você alterasse o estado diretamente, o React precisaria fazer muito mais trabalho para rastrear alterações, determinar quais ganchos do ciclo de vida executar e assim por diante. Como resultado, o React usa o
setState
para facilitar a vida. ”
Agora que descobrimos as alterações nos dados, vamos falar sobre como, em ambas as versões do nosso aplicativo, adicionar novos itens à lista de tarefas.
Adicionar novos itens à lista de tarefas
EaReativar
Veja como fazer isso no React.
createNewToDoItem = () => { this.setState( ({ list, todo }) => ({ list: [ ...list, { todo } ], todo: '' }) ); };
Aqui, o campo usado para
input
dados (
input
), tem o
value
do atributo. Esse atributo é atualizado automaticamente através do uso de um par de funções interconectadas que formam o que é chamado de ligação de dados bidirecional (se você nunca ouviu falar disso antes - espere um pouco, falaremos sobre isso na seção sobre como adicionar elementos ao aplicativo Vue). Criamos esse tipo de comunicação bidirecional devido à presença de um
onChange
evento
onChange
adicional anexado ao campo de
input
. Vamos dar uma olhada no código desse campo para que você possa entender o que está acontecendo aqui.
<input type="text" value={this.state.todo} onChange={this.handleInput}/>
A função
handleInput
chamada quando o valor do campo de
input
alterado. Isso leva à atualização do elemento
todo
, que está dentro do objeto
state
, configurando-o para o valor que está no campo de
input
. É assim que a função
handleInput
parece.
handleInput = e => { this.setState({ todo: e.target.value }); };
Agora, quando o usuário clica no botão
+
na página do aplicativo para adicionar um novo registro à lista, a função
createNewToDoItem
chama o método
this.setState
e passa a função. Esta função usa dois parâmetros. O primeiro é a matriz de
list
inteira do objeto
state
e o segundo é o elemento
todo
atualizado pela função
handleInput
. A função então retorna um novo objeto que contém a matriz de
list
antiga e adiciona um novo elemento
todo
ao final dessa matriz. O trabalho com a lista é organizado usando o operador de
spread
(se você nunca o conheceu antes, saiba que esse é um dos novos recursos do ES6 e procure detalhes sobre ele).
Por fim, uma string vazia é gravada em
todo
, que atualiza automaticamente o
value
no campo de
input
.
▍Vue
A construção a seguir é usada para adicionar um novo item à lista de tarefas no Vue.
createNewToDoItem() { this.list.push( { 'todo': this.todo } ); this.todo = ''; }
No Vue, o campo de entrada possui uma diretiva de
v-model
. Permite organizar a ligação de dados bidirecional. Dê uma olhada no código desse campo e fale sobre o que está acontecendo aqui.
<input type="text" v-model="todo"/>
A diretiva
v-model
vincula um campo a uma chave que existe em um objeto de dados chamado
toDoItem
. Quando a página é carregada, uma linha vazia é escrita em
toDoItem
, ela se parece com
todo: ''
.
Se já houver alguns dados, algo como
todo: 'add some text here'
, o mesmo texto entrará no campo de entrada, ou seja -
'add some text here'
. De qualquer forma, se retornarmos ao exemplo com uma sequência vazia, o texto que inserirmos no campo cairá, devido à ligação de dados, na propriedade
todo
. Essa é uma ligação de dados bidirecional, ou seja, a inserção de novos dados no campo leva ao registro desses dados no objeto de
data
e a atualização dos dados no objeto leva à aparência desses dados no campo.
Agora lembre-se da função
createNewToDoItem()
, sobre a qual falamos acima. Como você pode ver, colocamos o conteúdo de
todo
na matriz da
list
e, em seguida, escrevemos uma string vazia em
todo
.
Removendo itens de uma lista
EaReativar
Em React, esta operação é executada assim.
deleteItem = indexToDelete => { this.setState(({ list }) => ({ list: list.filter((toDo, index) => index !== indexToDelete) })); };
Enquanto a função
deleteItem
estiver no arquivo
ToDo.js
, você poderá acessá-la sem problemas no
ToDoItem.js
, passando essa função como uma propriedade para
<ToDoItem/>
. Aqui está o que parece:
<ToDoItem deleteItem={this.deleteItem.bind(this, key)}/>
Aqui passamos primeiro a função, que a torna disponível para componentes filhos. Além disso, ligamos
this
e passamos o parâmetro
key
. Este parâmetro é usado pela função para distinguir o elemento
ToDoItem
a ser excluído de outros elementos. Em seguida, dentro do componente
ToDoItem
, fazemos o seguinte.
<div className="ToDoItem-Delete" onClick={this.props.deleteItem}>-</div>
Tudo o que precisa ser feito para acessar a função localizada no componente pai é usar a construção
this.props.deleteItem
.
▍Vue
A exclusão de um item da lista no Vue é feita assim.
onDeleteItem(todo){ this.list = this.list.filter(item => item !== todo); }
O Vue requer uma abordagem ligeiramente diferente para remover elementos do que usamos no React. Ou seja, há três etapas a serem tomadas.
Primeiro, aqui está o que você precisa fazer no elemento para o qual você precisa chamar a função para excluí-la.
<div class="ToDoItem-Delete" @click="deleteItem(todo)">-</div>
Em seguida, você precisa criar a função de
emit
como um método no componente filho (neste caso, em
ToDoItem.vue
), que se parece com isso.
deleteItem(todo) { this.$emit('delete', todo) }
Além disso, você pode perceber que estamos adicionando
ToDoItem.vue
dentro do
ToDo.vue
.
<ToDoItem v-for="todo in list" :todo="todo" @delete="onDeleteItem" // <-- this :) :key="todo.id" />
Isso é chamado de ouvinte de eventos personalizado. Ele responde para
emit
chamadas com a linha de
delete
. Se ele captura um evento semelhante, chama a função
onDeleteItem
. Ele está localizado dentro do
ToDo.vue
e não no
ToDoItem.vue
. Essa função, como mencionado acima, simplesmente filtra a matriz de
todo
localizada no objeto de
data
para remover o elemento que foi clicado nela.
Além disso, vale ressaltar que no exemplo usando o Vue, pode-se simplesmente escrever o código relacionado à função de
emit
dentro do
@click
. Pode ser assim.
<div class="ToDoItem-Delete" @click="$emit('delete', todo)">-</div>
Isso reduziria o número de etapas necessárias para remover um item da lista de três para dois. Como proceder é uma questão de preferência do desenvolvedor.
Para resumir esta seção, podemos dizer que no React, o acesso às funções descritas nos componentes pai é organizado por meio deste
this.props
(dado que os
props
passados aos componentes filhos, que é uma técnica padrão que pode ser encontrada literalmente em qualquer lugar). No Vue, os componentes filhos devem acionar eventos usando a função de
emit
, e esses eventos já são tratados pelo componente pai.
Trabalhar com ouvintes de eventos
EaReativar
No React, os ouvintes de eventos para algo simples, como um evento de clique, são bastante simples. Aqui está um exemplo de criação de um manipulador de eventos de
click
para um botão que cria um novo item de tarefa.
<div className="ToDo-Add" onClick={this.createNewToDoItem}>+</div>
Tudo é organizado de maneira simples aqui, é muito semelhante ao processamento desses eventos usando JavaScript puro.
Deve-se observar que aqui, configurar ouvintes de eventos para pressionar as teclas, por exemplo, para
Enter
, leva um pouco mais do que no Vue. Aqui você precisa que o evento
onKeyPress
tratado da seguinte maneira. Aqui está o código para o campo de entrada.
<input type="text" onKeyPress={this.handleKeyPress}/>
A função
handleKeyPress
chama a função
createNewToDoItem
quando reconhece uma
handleKeyPress
em
Enter
. Parece assim.
handleKeyPress = (e) => { if (e.key === 'Enter') { this.createNewToDoItem(); } };
▍Vue
Os manipuladores de eventos no Vue são muito fáceis de configurar. Basta usar o símbolo
@
e especificar o tipo de ouvinte que queremos usar.
Por exemplo, para adicionar um ouvinte de evento de clique, você pode usar o seguinte código.
<div class="ToDo-Add" @click="createNewToDoItem()">+</div>
Observe que
@click
é a abreviação de
v-on:click
. Os ouvintes de eventos do Vue são bons em serem muito bem controlados. Por exemplo, anexar a construção
.once
ao ouvinte fará com que o ouvinte seja
.once
apenas uma vez.
Existem muitas abreviações que simplificam a escrita dos ouvintes que respondem às teclas digitadas no teclado. No React, como dissemos, isso leva mais tempo do que no Vue. Aqui é feito de maneira muito simples.
<input type="text" v-on:keyup.enter="createNewToDoItem"/>
Passando dados para componentes filho
EaReativar
Em React, as propriedades são passadas para o componente filho quando ele é criado. Por exemplo, assim:
<ToDoItem key={key} item={todo} />
Aqui você pode ver duas propriedades passadas para o componente
ToDoItem
. A partir de agora, eles podem ser acessados no componente filho via
this.props
.
Por exemplo, para acessar a propriedade
item.todo
, basta usar a construção
this.props.item
.
▍Vue
No Vue, as propriedades também são passadas para os componentes filhos quando eles são criados.
<ToDoItem v-for="todo in list" :todo="todo" :key="todo.id" @delete="onDeleteItem" />
Depois disso, eles são passados para a matriz
props
do componente filho, por exemplo, usando a construção
props: [ 'todo' ]
. Você pode acessar essas propriedades nos componentes filhos pelo nome; no nosso caso, é o nome
'todo'
.
Passando dados para o componente pai
EaReativar
No React, a função é passada primeiro ao componente filho como uma propriedade na qual o componente filho é chamado. Em seguida, está planejado chamar essa função, por exemplo, adicionando-a como manipulador
onClick
ou chamando-a chamando
this.props.whateverTheFunctionIsCalled
. Isso leva a uma chamada para a função localizada no componente pai. Este processo é descrito na seção sobre remoção de itens da lista.
▍Vue
Ao usar o Vue, em um componente filho, basta escrever uma função que transmita dados para a função pai. Uma função é gravada no componente pai que escuta eventos de transferência de valor. Quando um evento semelhante ocorre, essa função é chamada. Assim como o React, uma descrição desse processo pode ser encontrada na seção sobre remoção de itens da lista.
Sumário
Falamos sobre como adicionar, remover e modificar dados em aplicativos baseados no Vue e React, como transferir dados, na forma de propriedades, de componentes pai para filhos e como enviar dados de componentes filhos para pais. Acreditamos que, depois de analisar os exemplos de semelhanças e diferenças, Vue e React são visíveis, como se costuma dizer, a olho nu.
Obviamente, existem muitas outras pequenas diferenças entre o React e o Vue, mas espero que o que abordamos aqui sirva como uma boa base para entender como essas estruturas funcionam. As estruturas são frequentemente analisadas ao escolher a plataforma certa para um novo projeto. Esperamos que este material ajude a fazer essa escolha.
Caros leitores! Que diferenças entre React e Vue, na sua opinião, são as mais importantes que afetam a escolha de uma estrutura específica, por exemplo, como base para um determinado projeto?
