Comparación de marcos JS: React, Vue e Hyperapp

El autor del material, cuya traducción publicamos hoy, cree que Hyperapp es una alternativa notable a marcos web como React o Vue . Él dice que la razón de esta afirmación fue que descubrió que Hyperapp era más fácil de aprender que los dos marcos. Su idea ha sido criticada, ya que parece que se basa únicamente en su opinión, y este enfoque simplemente no le da a otros marcos la oportunidad de mostrar sus puntos fuertes. Este artículo está dirigido a un análisis objetivo de Hyperapp, React y Vue, basado en ejemplos simples que demuestran sus capacidades y en función de los resultados de sus pruebas.



Ejemplo # 1: aplicación de contador


La implementación de la aplicación de contador es probablemente uno de los ejemplos más utilizados en la programación reactiva. Es extremadamente simple y comprensible:

  • Necesitamos el count variable, que almacenará el valor del contador.
  • Se necesitarán dos métodos para aumentar y disminuir el count variable.
  • Se requiere un mecanismo para mostrar el valor almacenado en el count y presentarlo al usuario.
  • Se necesitan dos botones que están vinculados a los métodos apropiados, lo que permite al usuario actuar sobre la variable de count .

Aquí hay una implementación de este ejemplo utilizando los marcos en cuestión.

▍Reaccionar


 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álisis


Si no está familiarizado con estos marcos, o incluso con al menos uno de ellos, entonces aquí, probablemente, encontrará algo incomprensible. Así que analicemos este código.

  • Cuando se usan los tres marcos, hay comandos de import al comienzo del código de la aplicación.
  • React utiliza un paradigma orientado a objetos. Esto crea una clase para el componente Counter . Vue sigue el mismo camino. Aquí se crea una nueva instancia de la clase Vue , se le pasa información. Y finalmente, Hyperapp usa un paradigma funcional, usa entidades independientes, view , state y actions .
  • Si hablamos del count variable, en React se inicializa en el constructor del componente, y en Vue e Hyperapp es una propiedad de los objetos de data y de state , respectivamente.
  • Si profundizamos en la exploración de estas aplicaciones, podemos ver que React y Vue usan métodos muy similares para interactuar con la variable de count . En React, para cambiar el estado de una aplicación, se setState método setState heredado de React.Component . En Vue, el valor de this.count cambia directamente. Los métodos de Hyperapp se escriben utilizando la sintaxis de la función de flecha ES6. Entre los marcos en cuestión, él es el único que usa esto, ya que React y Vue se ven obligados a usar this palabra clave dentro de sus métodos. Los métodos de Hyperapp, por otro lado, requieren que, como argumento, se les pase un objeto con estado de aplicación. Esto significa que es más probable que sean reutilizables en varios contextos.
  • La parte de la aplicación que se encarga de enviar datos a la página se ve casi igual en los tres ejemplos. La peculiaridad de Vue es que cuando se usa este marco, la función h debe pasarse al subsistema de representación. Hyperapp usa onclick lugar de onclick , y aquí se accede a la variable de count diferente a React y Vue, debido a las peculiaridades de cómo se almacena el estado de la aplicación en cada marco.
  • Y finalmente, los tres marcos usan el enlace al elemento #app . En cada uno de ellos, esta operación se realiza de manera diferente. Cabe señalar que en Vue esta operación parece la más simple y más comprensible y le da al desarrollador un diseño más flexible, trabajando con el selector de elementos y no con el elemento en sí.

▍ Conclusiones


Si compara directamente el código que resuelve el mismo problema escrito usando los tres marcos, resulta que Hyperapp, para la implementación de la aplicación de contador, requiere la menor cantidad de líneas de código, y este es el único marco que utiliza un enfoque funcional. Sin embargo, la cantidad de código escrito usando Vue, si cuenta el número de caracteres, resulta un poco menos, y el uso de un selector de elementos en él se ve muy bien. El código de la aplicación React parece ser el más largo, pero esto no significa que sea mucho más difícil de entender que el código escrito para trabajar con otros marcos analizados.

Ejemplo No. 2: trabajar con código asincrónico


Es posible que, en la práctica, tenga que lidiar con código asincrónico. Una de las operaciones asincrónicas más comunes es enviar una solicitud a alguna API. Para los fines de este ejemplo, se utiliza la API JSONPlaceholder , que contiene datos condicionales y listas de publicaciones. Esto es lo que haremos aquí:

  • Guardamos la matriz para publicarla en el estado de la aplicación.
  • Llamamos, utilizando el método apropiado, fetch() , indicando la URL que necesitamos, esperamos a que lleguen los datos, analizamos el código JSON recibido, que es una matriz de objetos, y finalmente actualizamos la variable de posts escribiendo los datos recibidos.
  • Mostramos un botón en la página que llama al método que carga la lista de publicaciones.
  • Enumere las publicaciones de las posts con las teclas.

Considere un código que implementa el esquema de acción anterior.

▍Reaccionar


 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álisis


Analicemos este código y comparemos los tres marcos investigados.

  • Como en el ejemplo anterior, el almacenamiento del estado de la aplicación, la salida de datos y la conexión al elemento de página son muy similares en los tres marcos. Aquí se observan las mismas diferencias, que ya hemos mencionado anteriormente.
  • Descargar datos usando la función fetch() es una operación bastante simple; funciona como se espera en todos los marcos. Sin embargo, la principal diferencia aquí es que Hyperapp admite realizar operaciones asincrónicas de manera un poco diferente a otros marcos. En lugar de modificar el estado directamente, dentro de una acción asincrónica, esta acción llama a otra acción síncrona, que recibe los datos y los convierte a un formato adecuado. Esto hace que el núcleo de la aplicación sea más funcional y más adecuado para dividirse en partes pequeñas que son potencialmente adecuadas para su reutilización. Este enfoque, además, ayuda a evitar algunos de los problemas inherentes a las devoluciones de llamada anidadas que pueden surgir en situaciones como estas.
  • Si hablamos del tamaño del código, entonces la aplicación Hyperapp nuevamente necesita menos líneas de código para lograr el mismo objetivo, pero el código Vue parece más corto, y si cuenta el número de caracteres en el código, es más corto que otras opciones.

▍ Conclusiones


La realización de operaciones asincrónicas resultó ser igualmente simple en todos los marcos. Hyperapp puede llevar al desarrollador a escribir código más funcional y modular cuando trabaje con acciones asincrónicas, pero los otros dos marcos también hacen un excelente trabajo de su tarea y, en este sentido, le dan al desarrollador la oportunidad de elegir.

Ejemplo 3: enumerar el elemento del elemento para una aplicación de tareas pendientes


Las aplicaciones de tareas pendientes son probablemente el ejemplo más famoso en programación reactiva. Aparentemente, se implementó algo similar utilizando casi todos los marcos existentes. Aquí no implementaremos toda la aplicación. En cambio, centrémonos en un componente simple sin estado para explorar las posibilidades de los marcos en estudio para crear pequeños bloques de construcción de aplicaciones web adecuadas para su reutilización.

Considere la implementación del componente utilizando los marcos estudiados. Sin embargo, en este ejemplo, ampliaremos las opciones de código bajo consideración al considerar un componente React escrito en un estilo funcional.

▍React (estilo funcional)


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

▍Reaccionar


 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


Tenga en cuenta que Hyperapp también usa un estilo funcional.

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

▍Análisis


  • Reaccionar, con respecto al uso de patrones de codificación, es el marco más flexible. Admite componentes funcionales, así como componentes diseñados como clases. Además, React, en su forma estándar, también admite componentes Hyperapp.
  • Hyperapp también admite componentes funcionales React. Esto significa que cuando se trabaja con Hyperapp y React, hay mucho espacio para la experimentación.
  • Vue ocupa el último lugar en esta prueba. Tiene una sintaxis bastante extraña que es difícil de entender de inmediato, incluso para aquellos familiarizados con React o Hyperapp.
  • Si hablamos de la longitud del código, entonces todos los ejemplos tienen tamaños muy similares. Lo único que se puede notar aquí es que el código en React, en una de las opciones, resultó ser un poco más voluminoso que en la otra.

▍ Conclusiones


Toma tiempo acostumbrarse a Vue, ya que sus plantillas son ligeramente diferentes de las plantillas de los otros dos marcos. React es extremadamente flexible, admite varios enfoques utilizados para crear componentes. Al mismo tiempo, todo es muy simple en Hyperapp, y también es compatible con React, que le permite cambiar el marco, si es necesario, en alguna etapa del proyecto.

Comparación de los métodos del ciclo de vida de los componentes.


Otra consideración importante que afecta la elección de un marco son los eventos del ciclo de vida de los componentes que admite, a los que puede suscribirse y que puede procesar de acuerdo con las necesidades del desarrollador. Aquí hay una tabla basada en un análisis de la API de los sistemas en estudio.
El evento
Reaccionar
Vue
Hyperapp
Inicialización
constructor
beforeCreate, creado
-
Montaje
comoinentDidMount
beforeMount, montado
crear
Actualización
componentDidUpdate
beforeUpdate, actualizado
actualización
Desmontaje
componentWillUnmount
-quitar
Destrucción
-antes de destruir, destruido
ondestroy

▍Análisis


Esto es lo que puedes entender al analizar esta tabla:

  • La mayoría de los ganchos de ciclo de vida están en Vue. Con su ayuda, el programador tiene la oportunidad de procesar todo lo que sucede con el componente, ya sea antes o después del evento correspondiente. Esto puede ser útil para administrar componentes complejos.
  • Los ganchos del ciclo de vida de React e Hyperapp son muy similares, aunque React combina el procesamiento de eventos que ocurren durante el desmontaje y destrucción de un componente, mientras que Hyperapp también actúa con eventos de creación y montaje de un componente. Ambos le dan al desarrollador un número suficiente de posibilidades para procesar eventos del ciclo de vida.
  • Vue no maneja el evento de desmontaje (por lo que puede comprender analizando la API de marco), sino que depende de los ganchos asociados con la destrucción del componente. React no maneja un evento de eliminación de componentes, permitiendo que solo se procese un evento de desmontaje de componentes. Hyperapp no ​​ofrece ganchos para manejar eventos de creación de componentes, sino que se basa completamente en eventos de montaje. Dependiendo de sus necesidades y experiencia, estas diferencias deben tenerse en cuenta al diseñar una aplicación, teniendo en cuenta la posibilidad de procesar eventos del ciclo de vida de los componentes.

▍ Conclusiones


En general, se puede observar que los métodos para manejar eventos que ocurren durante el ciclo de vida de los componentes son compatibles con todos los marcos. Estos métodos resolverán muchos problemas. Los tres marcos ofrecen ganchos para todo tipo de eventos, pero existen pequeñas diferencias entre ellos, cuya fuente pueden ser las características internas de los marcos y las diferencias en su implementación. Quizás Vue en esta área está un paso por delante de otros sistemas, ofreciendo un sistema de procesamiento de eventos más detallado, que le permite manejar eventos del ciclo de vida antes o después de que ocurran.

Comparación de rendimiento del marco


Además de la conveniencia de usar el marco y las técnicas de programación utilizadas para trabajar con él, muchos desarrolladores están seriamente preocupados por el rendimiento de los marcos, especialmente para aplicaciones bastante complejas. Una fuente valiosa de información sobre el rendimiento de varios marcos es el proyecto js-framework-benchmark .

Por lo tanto, eche un vistazo a los resultados de las pruebas de React, Vue e Hyperapp.

▍Trabajar con mesas


Aquí están los resultados de las pruebas de los marcos para trabajar con tablas. El indicador en las celdas de la tabla corresponde a la duración de la operación ± desviación estándar. El resultado de dividir el indicador obtenido por el mejor indicador se muestra entre paréntesis.


Análisis


  • Las operaciones en las que las teclas (sin clave) no se utilizan para la salida de datos son mucho más rápidas que las operaciones en las que se utilizan claves (con clave).
  • La más rápida de las seis opciones consideradas fue la que usa React sin el uso de teclas, lo que muestra un rendimiento impresionante en todas las pruebas.
  • Si compara Vue y React cuando trabaja con teclas, Vue tiene una ligera ventaja. Al mismo tiempo, si compara React y Vue en variantes donde no se utilizan claves, Vue muestra un rendimiento significativamente menor que React.
  • Vue e Hyperapp, como puede ver en los resultados, tienen algunas dificultades con la prueba, en la que se realiza la actualización parcial de la tabla, y React se muestra bien en ella, probablemente debido a alguna optimización destinada a acelerar operaciones

▍ Carga, lanzamiento, tamaños de código


Aquí hay una tabla con los resultados de un estudio de indicadores relacionados con la velocidad de lanzamiento del marco, su tamaño y el uso del hilo principal.


Análisis


  • El código Hyperapp resultó ser el más pequeño entre los marcos estudiados. El código React y Vue son aproximadamente del mismo tamaño.
  • Hyperapp necesita menos tiempo para iniciarse. La razón de esto, por supuesto, es el pequeño tamaño del código marco y el enfoque minimalista para diseñar su API.
  • Vue, cuando se trata del tiempo que lleva lanzar el framework, es un poco más rápido que React.

▍Trabajando con memoria


Ahora considere los resultados de probar la asignación de memoria.


Análisis


  • Hyperapp es el marco más poco exigente en términos de consumo de memoria.
  • En general, se puede observar que todos los marcos no consumen mucha memoria. Esto sugiere que ellos, en las computadoras modernas, funcionarán aproximadamente igual.

▍ Conclusiones


Si, al desarrollar un proyecto, necesita alcanzar el máximo rendimiento, debe comprender, en primer lugar, qué tipo de aplicación está desarrollando y, en segundo lugar, determinar claramente las necesidades de esta aplicación. Si combina el análisis de rendimiento de los tres marcos, tiene la sensación de que Vue y React son más adecuados para aplicaciones más complejas, y Hyperapp es mejor en aplicaciones de menor escala que necesitan procesar menos datos, que requieren un lanzamiento lo más rápido posible, y quién puede necesitar trabajar en computadoras que no sean las más rápidas.

Sin embargo, vale la pena recordar que las pruebas de rendimiento utilizadas aquí están lejos de la vida real, de algún tipo de escenario promedio. Por lo tanto, después de haberlos probado y comparado en un proyecto real, puede ver otros resultados.

Notas adicionales


Cabe señalar que comparar marcos web puede parecerse a algo como comparar manzanas con naranjas. Aquí hay algunas otras consideraciones con respecto a React, Vue e Hyperapp que pueden ser útiles para elegir un marco específico para un proyecto:

  • React evita el problema de que los elementos JSX vecinos deben estar envueltos en el elemento padre, introduciendo el concepto de fragmentos , elementos que le permiten agrupar un conjunto de elementos descendientes sin agregar nodos adicionales al DOM.
  • React proporciona al desarrollador componentes de orden superior , mientras que Vue usa mixins para reutilizar la funcionalidad del componente.
  • Vue utiliza más plenamente el concepto de separación de responsabilidades, separando la estructura y la funcionalidad de la aplicación mediante plantillas .
  • Hyperapp, en comparación con React y Vue, parece un sistema que proporciona una API de nivel inferior. El código de las aplicaciones de Hyperapp resulta ser más corto, brinda una gran flexibilidad, lo que puede ser útil en los casos en que el desarrollador quiera abordarlo ajustando y estudiando sus mecanismos internos.

Resumen


El autor de este material cree que si lee hasta este punto, ya tiene una idea de cuál de los marcos estudiados aquí se adapta mejor a sus necesidades. Al final, no estábamos hablando sobre cuál de los marcos es el mejor, sino sobre cuál de ellos es más capaz de mostrarse en diversas situaciones. Como resultado, podemos sacar las siguientes conclusiones generales:

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

! -?


, - 10% :)

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


All Articles