Comparação de estruturas JS: React, Vue e Hyperapp

O autor do material, cuja tradução publicamos hoje, acredita que o Hyperapp é uma alternativa digna de nota para estruturas da web como React ou Vue . Ele diz que o motivo dessa alegação foi que ele descobriu que o Hyperapp era mais fácil de aprender do que as duas estruturas. Sua idéia foi criticada, pois parece que se baseia unicamente em sua opinião, e essa abordagem simplesmente não dá a outras estruturas a oportunidade de mostrar seus pontos fortes. Este artigo tem como objetivo uma análise objetiva do Hyperapp, React e Vue, com base em exemplos simples que demonstram seus recursos e com base nos resultados dos testes.



Exemplo 1: aplicação contra


A implementação do aplicativo de contador é provavelmente um dos exemplos mais usados ​​na programação reativa. É extremamente simples e compreensível:

  • Precisamos da count variáveis, que armazenará o valor do contador.
  • Dois métodos serão necessários para aumentar e diminuir a count variáveis.
  • É necessário um mecanismo para exibir o valor armazenado na count e apresentá-lo ao usuário.
  • São necessários dois botões vinculados aos métodos apropriados, permitindo que o usuário atue na variável count .

Aqui está uma implementação deste exemplo usando as estruturas em questão.

EaReativar


 import React from "react"; import ReactDOM from "react-dom"; Class Counter extends React.Component {   constructor(props) {       super(props);       this.state = { count: 0};   }   down(value) {       this.setState(state => ({ count: state.count - value }));   }   up(value) {       this.setState(state => ({ count: state.count + value }));   }   render() {       return (           <div>               <h1>{this.state.count}</h1>               <button onClick = {() => this.down(1)}>-</button>               <button onClick = {() => this.up(1)}>+</button>           </div>       );   } } ReactDOM.render(<Counter />, document.querySelector("#app")); 

▍Vue


 import Vue from "vue"; new Vue({   data: { count: 0 },   methods: {       down: function(value) {           this.count -= value;       },       up: function(value) {           this.count += value;       }   },   render: function(h) {       return(           <div>               <h1>{this.count}</h1>               <button onClick={() => this.down(1)}>-</button>               <button onClick={() => this.up(1)}>+</button>           </div>       );   },   el: "#app" }); 

▍Hyperapp


 import { h, app } from "hyperapp"; const state = {   count: 0 }; const actions = {   down: value => state => ({ count: state.count - value}),   up: value => state => ({ count: state.count + value}) }; const view = (state, actions) => (   <div>       <h1>{state.count}</h1>       <button onclick={() => actions.down(1)}>-</button>       <button onclick={() => actions.up(1)}>+</button>   </div> ); app(state, actions, view, document.querySelector("#app")); 

▍Análise


Se você não estiver familiarizado com essas estruturas, ou mesmo com pelo menos uma delas, então aqui, provavelmente, você encontrará algo incompreensível. Então, vamos analisar esse código.

  • Ao usar todas as três estruturas, existem comandos de import no início do código do aplicativo.
  • React usa um paradigma orientado a objetos. Isso cria uma classe para o componente Counter . Vue segue o mesmo caminho. Aqui, uma nova instância da classe Vue é criada, as informações são passadas para ela. E, finalmente, o Hyperapp usa um paradigma funcional, usa view , state e actions entidades independentes.
  • Se falamos sobre a count variáveis, no React ele é inicializado no construtor do componente, e no Vue e no Hyperapp é uma propriedade dos objetos de data e state , respectivamente.
  • Se continuarmos a explorar esses aplicativos, podemos ver que o React e o Vue usam métodos muito semelhantes para interagir com a variável count . Em React, para alterar o estado de um aplicativo, React.Component o método setState herdado de React.Component . No Vue, o valor desta this.count alterado diretamente. Os métodos Hyperapp são gravados usando a sintaxe da função de seta ES6. Entre os frameworks em questão, ele é o único a usar isso, já que React e Vue são forçados a usar a palavra this chave this dentro de seus métodos. Os métodos Hyperapp, por outro lado, exigem que eles, como argumento, passem um objeto com o estado do aplicativo. Isso significa que é mais provável que sejam reutilizáveis ​​em vários contextos.
  • A parte do aplicativo responsável pela saída de dados para a página parece quase a mesma nos três exemplos. A peculiaridade do Vue é que, ao usar essa estrutura, a função h deve ser passada para o subsistema de renderização. O Hyperapp usa onclick vez de onclick , e aqui a variável count é acessada de maneira diferente do React e do Vue, devido às peculiaridades de como o estado do aplicativo é armazenado em cada estrutura.
  • E, finalmente, todas as três estruturas usam a ligação ao elemento #app . Em cada um deles, esta operação é realizada de maneira diferente. Deve-se notar que no Vue essa operação parece a mais simples e compreensível e oferece ao desenvolvedor um design mais flexível, trabalhando com o seletor de elementos e não com o próprio elemento.

▍ Conclusões


Se você comparar diretamente o código que resolve o mesmo problema escrito usando as três estruturas, o Hyperapp, para a implementação do aplicativo de contador, exige o menor número de linhas de código e essa é a única estrutura que usa uma abordagem funcional. No entanto, a quantidade de código escrita usando o Vue, se você contar o número de caracteres, será um pouco menor, e o uso de um seletor de elementos nele parecerá muito bom. O código do aplicativo React parece ser o mais longo, mas isso não significa que é muito mais difícil de entender do que o código escrito para trabalhar com outras estruturas analisadas.

Exemplo No. 2: Trabalhando com Código Assíncrono


É possível que, na prática, você tenha que lidar com código assíncrono. Uma das operações assíncronas mais comuns é enviar uma solicitação para alguma API. Para os fins deste exemplo, é usada a API JSONPlaceholder , que contém dados condicionais e lista as publicações. Aqui está o que vamos fazer aqui:

  • Nós salvamos a matriz para postá-la no estado do aplicativo.
  • Chamamos, usando o método apropriado, fetch() , indicando a URL que precisamos, aguardamos a chegada dos dados, analisamos o código JSON recebido, que é uma matriz de objetos, e finalmente atualizamos a variável posts escrevendo os dados recebidos.
  • Exibimos um botão na página que chama o método que carrega a lista de publicações.
  • Liste as postagens de posts usando chaves.

Considere um código que implementa o esquema de ação acima.

EaReativar


 import React from "react"; import ReactDOM from "react-dom"; class PostViewer extends React.Component {   constructor(props) {       super(props);       this.state = { posts: [] };   }   getData() {       fetch(`https://jsonplaceholder.typicode.com/posts`)       .then(response => response.json())       .then(json => {           this.setState(state => ({ posts: json}));       });   }   render() {       return (           <div>               <button onClick={() => this.getData()}>Get posts</button>               {this.state.posts.map(post => (                   <div key={post.id}>                       <h2><font color="#3AC1EF">{post.title}</font></h2>                       <p>{post.body}</p>                   </div>               ))}           </div>       );   } } ReactDOM.render(<PostViewer />, document.querySelector("#app")); 

▍Vue


 import Vue from "vue"; new Vue({   data: { posts: [] },   methods: {       getData: function(value) {           fetch(`https://jsonplaceholder.typicode.com/posts`)           .then(response => response.json())           .then(json => {               this.posts = json;           });       }   },   render: function(h) {       return (           <div>               <button onClick={() => this.getData()}>Get posts</button>               {this.posts.map(post => (                   <div key={post.id}>                       <h2><font color="#3AC1EF">{post.title}</font></h2>                       <p>{post.body}</p>                   </div>               ))}           </div>       );   },   el: "#app" }); 

▍Hyperapp


 import { h, app } from "hyperapp"; const state = {   posts: [] }; const actions = {   getData: () => (state, actions) => {       fetch(`https://jsonplaceholder.typicode.com/posts`)       .then(response => response.json())       .then(json => {           actions.getDataComplete(json);       });   },   getDataComplete: data => state => ({ posts: data }) }; const view = (state, actions) => (   <div>       <button onclick={() => actions.getData()}>Get posts</button>       {state.posts.map(post => (           <div key={post.id}>               <h2><font color="#3AC1EF">{post.title}</font></h2>               <p>{post.body}</p>           </div>       ))}   </div> ); app(state, actions, view, document.querySelector("#app")); 

▍Análise


Vamos analisar esse código e comparar as três estruturas investigadas.

  • Como no exemplo anterior, o armazenamento do estado do aplicativo, a saída de dados e a conexão com o elemento page são muito semelhantes nas três estruturas. Aqui são observadas as mesmas diferenças, que já mencionamos acima.
  • Baixar dados usando a função fetch() é uma operação bastante simples; funciona como esperado em todas as estruturas. A principal diferença aqui, no entanto, é que o Hyperapp suporta operações assíncronas de maneira um pouco diferente de outras estruturas. Em vez de modificar o estado diretamente, dentro de uma ação assíncrona, essa ação chama outra ação síncrona, que recebe os dados e os converte em um formato adequado. Isso torna o núcleo do aplicativo mais funcional e mais adequado para quebrar em pequenas peças potencialmente adequadas para reutilização. Além disso, essa abordagem ajuda a evitar alguns dos problemas inerentes aos retornos de chamada aninhados que podem surgir em situações como essas.
  • Se falarmos sobre o tamanho do código, o aplicativo Hyperapp novamente precisará de menos linhas de código para atingir o mesmo objetivo, mas o código do Vue parece mais conciso e, se você contar o número de caracteres no código, é mais curto do que outras opções.

▍ Conclusões


A realização de operações assíncronas acabou sendo igualmente simples em todas as estruturas. A Hyperapp pode levar o desenvolvedor a escrever código mais funcional e modular ao trabalhar com ações assíncronas, mas as outras duas estruturas também fazem um excelente trabalho de sua tarefa e, nesse sentido, oferecem ao desenvolvedor a oportunidade de escolher.

Exemplo 3: componente de item de lista para um aplicativo de Tarefas Pendentes


Os aplicativos Tarefas Pendentes são provavelmente o exemplo mais famoso da programação reativa. Aparentemente, algo semelhante foi implementado usando quase todas as estruturas existentes. Aqui não implementaremos o aplicativo inteiro. Em vez disso, vamos nos concentrar em um componente sem estado simples, a fim de explorar as possibilidades das estruturas em estudo para criar pequenos blocos de construção de aplicativos da Web adequados para reutilização.

Considere a implementação do componente usando as estruturas estudadas. Neste exemplo, no entanto, expandiremos as opções de código em consideração, considerando um componente React gravado em um estilo funcional.

EaReativar (estilo funcional)


 function TodoItem(props) {   return (       <li class={props.done ? "done" : ""} onclick={() => props.toggle(props.id)}>           {props.value}       </li>   ); } 

EaReativar


 class TodoItem extends React.Component {   render () {       return (           <li class={this.props.done ? "done" : ""} onclick={() => this.props.toggle(this.props.id)}>               {this.props.value}           </li>       );   } } 

▍Vue


 var TodoItem = Vue.component("todoitem", {   props: ["id", "value", "done", "toggle"],   template:       '<li v-bind:class="{done : done}" v-on:click="toggle(id)">{{value}}</li>' }); 

▍Hyperapp


Observe que o Hyperapp também usa um estilo funcional.

 const TodoItem = ({ id, value, done, toggle }) = (   <li class={done ? "done" : ""} onclick={() => toggle(id)}>       {value}   </li> ); 

▍Análise


  • O React, com relação ao uso de padrões de codificação, é a estrutura mais flexível. Ele suporta componentes funcionais, bem como componentes projetados como classes. Além disso, o React, em sua forma padrão, também suporta componentes Hyperapp.
  • O Hyperapp também suporta componentes funcionais do React. Isso significa que, ao trabalhar com o Hyperapp e o React, há muito espaço para experimentação.
  • Vue ocupa a última posição neste teste. Tem uma sintaxe bastante estranha que é difícil de entender imediatamente, mesmo para aqueles familiarizados com React ou Hyperapp.
  • Se falamos sobre o comprimento do código, todos os exemplos têm tamanhos muito semelhantes. A única coisa que pode ser notada aqui é que o código no React, em uma das opções, acabou sendo um pouco mais volumoso do que na outra.

▍ Conclusões


Leva algum tempo para se acostumar com o Vue, pois seus modelos são um pouco diferentes dos modelos das outras duas estruturas. O React é extremamente flexível, suporta várias abordagens usadas para criar componentes. Ao mesmo tempo, tudo é muito simples no Hyperapp e também é compatível com o React, que permite alterar a estrutura, se necessário, em algum momento do projeto.

Comparação dos métodos do ciclo de vida dos componentes


Outra consideração importante que afeta a escolha de uma estrutura é os eventos do ciclo de vida do componente que ela suporta, nos quais você pode se inscrever e que pode processar de acordo com as necessidades do desenvolvedor. Aqui está uma tabela baseada em uma análise da API dos sistemas em estudo.
Evento
Reagir
Vue
Hyperapp
Inicialização
construtor
beforeCreate, criado
-
Montagem
comoinentDidMount
beforeMount, montado
criar
Update
componentDidUpdate
beforeUpdate, atualizado
atualização
Desmontando
componentWillUnmount
-onremove
Destruição
-antes de destruir, destruído
ondestroy

▍Análise


Aqui está o que você pode entender analisando esta tabela:

  • A maioria dos ganchos do ciclo de vida está no Vue. Com a ajuda deles, o programador tem a oportunidade de processar tudo o que acontece com o componente, antes ou depois do evento correspondente. Isso pode ser útil para gerenciar componentes complexos.
  • Os ganchos do ciclo de vida do React e Hyperapp são muito semelhantes, embora o React combine o processamento de eventos que ocorrem durante a desmontagem e destruição de um componente, enquanto o Hyperapp também faz o mesmo com a criação e montagem de eventos para um componente. Ambos oferecem ao desenvolvedor um número suficiente de possibilidades para processar eventos do ciclo de vida.
  • O Vue não lida com o evento desmontar (até onde você pode entender analisando a API da estrutura), em vez disso, conta com ganchos associados à destruição do componente. React não manipula um evento de interrupção de componente, permitindo que apenas um evento de desmontagem de componente seja processado. O Hyperapp não oferece ganchos para manipular eventos de criação de componentes, mas depende inteiramente de eventos de montagem. Dependendo de suas necessidades e experiência, essas diferenças devem ser consideradas ao projetar um aplicativo, levando em consideração a possibilidade de processar eventos do ciclo de vida dos componentes.

▍ Conclusões


Em geral, pode-se observar que os métodos para manipular eventos que ocorrem durante o ciclo de vida dos componentes suportam todas as estruturas. Esses métodos resolverão muitos problemas. Todas as três estruturas oferecem ganchos para todos os tipos de eventos, mas há pequenas diferenças entre elas, cuja origem pode ser os recursos internos das estruturas e as diferenças em sua implementação. Talvez o Vue nessa área esteja um passo à frente de outros sistemas, oferecendo um sistema de processamento de eventos mais detalhado, permitindo que você lide com eventos do ciclo de vida antes ou depois que eles ocorrem.

Comparação de desempenho da estrutura


Além da conveniência de usar a estrutura e das técnicas de programação usadas para trabalhar com ela, muitos desenvolvedores estão seriamente preocupados com o desempenho das estruturas, especialmente para aplicativos bastante complexos. Uma fonte valiosa de informações sobre o desempenho de várias estruturas é o projeto js-framework-benchmark .

Portanto, dê uma olhada nos resultados dos testes React, Vue e Hyperapp.

▍Trabalhando com tabelas


Aqui estão os resultados dos testes das estruturas para trabalhar com tabelas. O indicador nas células da tabela corresponde à duração da operação ± desvio padrão. O resultado da divisão do indicador obtido pelo melhor indicador é mostrado entre parênteses.


Análise


  • As operações nas quais as chaves (sem chave) não são usadas para saída de dados são muito mais rápidas do que as operações nas quais as chaves são usadas (com chave).
  • A mais rápida das seis opções consideradas foi a que utiliza o React sem o uso de teclas, o que mostra um desempenho impressionante em todos os testes.
  • Se você comparar o Vue e o React ao trabalhar com chaves, o Vue terá uma pequena vantagem. Ao mesmo tempo, se você comparar o React e o Vue em variantes nas quais as chaves não são usadas, o Vue exibirá um desempenho significativamente menor que o React.
  • O Vue e o Hyperapp, como você pode ver nos resultados, têm algumas dificuldades com o teste, no qual a atualização parcial da tabela é realizada, e o React se mostra bem nele, provavelmente devido a alguma otimização que visa acelerar tal operações.

OadCarregando, iniciando, tamanhos de código


Aqui está uma tabela com os resultados de um estudo de indicadores relacionados à velocidade de lançamento do framework, ao seu tamanho e ao uso do thread principal.


Análise


  • O código Hyperapp acabou sendo o menor entre os frameworks estudados. Os códigos React e Vue são aproximadamente do mesmo tamanho.
  • O Hyperapp precisa de menos tempo para iniciar. A razão para isso, é claro, é o tamanho pequeno do código da estrutura e a abordagem minimalista para projetar sua API.
  • Vue, quando se trata do tempo necessário para iniciar o framework, é um pouco mais rápido que o React.

▍Trabalhando com memória


Agora considere os resultados do teste de alocação de memória.


Análise


  • O Hyperapp é a estrutura menos exigente em termos de consumo de memória.
  • Em geral, pode-se notar que todas as estruturas não consomem muita memória. Isso sugere que eles, em computadores modernos, funcionarão aproximadamente da mesma forma.

▍ Conclusões


Se, ao desenvolver um projeto, você precisar alcançar o desempenho máximo, primeiro entenda que tipo de aplicativo está desenvolvendo e, em segundo lugar, para determinar claramente as necessidades desse aplicativo. Se você combinar a análise de desempenho das três estruturas, terá a sensação de que o Vue e o React são mais adequados para aplicativos mais complexos, e o Hyperapp é melhor em aplicativos menores que precisam processar menos dados, o que exige a execução o mais rápida possível, e quem pode precisar trabalhar nos computadores não mais rápidos.

No entanto, vale lembrar que os testes de desempenho usados ​​aqui estão longe da vida real, de algum tipo de cenário médio. Portanto, depois de testá-los e compará-los em um projeto real, você pode ver outros resultados.

Notas adicionais


Deve-se notar que a comparação de estruturas da Web pode parecer algo como comparar maçãs com laranjas. Aqui estão algumas outras considerações sobre React, Vue e Hyperapp que podem ser úteis na escolha de uma estrutura específica para um projeto:

  • A reação ignora o problema de que os elementos JSX vizinhos devem ser agrupados no elemento pai, introduzindo o conceito de fragmentos - elementos que permitem agrupar um conjunto de elementos descendentes sem incluir nós adicionais no DOM.
  • O React fornece ao desenvolvedor componentes de ordem superior , enquanto o Vue usa mixins para reutilizar a funcionalidade do componente.
  • O Vue utiliza mais completamente o conceito de separação de responsabilidades, separando a estrutura e a funcionalidade do aplicativo usando modelos .
  • O Hyperapp, quando comparado ao React e ao Vue, parece um sistema que fornece uma API de nível inferior. O código dos aplicativos Hyperapp acaba sendo mais curto, oferece grande flexibilidade, o que pode ser útil nos casos em que o desenvolvedor pode querer enfrentá-lo ajustando e pesquisando seus mecanismos internos.

Sumário


O autor deste material acredita que, se você ler até este ponto, já terá uma compreensão de qual das estruturas estudadas aqui melhor se adequa às suas necessidades. No final, não estávamos falando sobre qual das estruturas é a melhor, mas sobre qual delas é mais capaz de se mostrar em várias situações. Como resultado, podemos tirar as seguintes conclusões gerais:

  • React — , , , - , . , , , , . , React — , .
  • Vue , - JavaScript-, — . React, , , , React - . Vue , , , , React.
  • , , Hyperapp — , , — . , React Vue, . , . , Hyperapp, , , , Hyperapp-, . , , Hyperapp, , , , React Vue, .

! -?


, - 10% :)

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


All Articles