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% :)