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

Este es un pequeño artículo de respuesta a la publicación "Comparación de marcos JS: React, Vue e Hyperapp" . En general, no soy un gran admirador de tales comparaciones. Sin embargo, dado que estábamos hablando de un marco tan marginal como Hyperapp, en comparación con mastodontes como React y Vue, pensé, ¿por qué no considerar los mismos ejemplos en Svelte ? Por así decirlo, para completar la imagen. Además, lleva literalmente 5 minutos. Vamos!

imagen

Si de repente no está familiarizado con Svelte y el concepto de marcos desaparecidos, puede leer los artículos "Marco JS que desaparece mágicamente" y "Marco que desaparece" .

Para comodidad de los lectores, copié los ejemplos del artículo original debajo de los spoilers para que sea más conveniente comparar. Bueno, empecemos.

Ejemplo No. 1: aplicación de contador


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")); 


▍Svelte


 <div> <h1>{count}</h1> <button on:click="set({count: count - 1})">-</button> <button on:click="set({count: count + 1})">+</button> </div> 

→ Un ejemplo de trabajo.

▍Análisis


Un componente Svelte es un archivo html que tiene el notorio formato de componente de archivo único (SFC), de una forma u otra, ya utilizado en Vue , Ractive , Riot y algunos otros marcos. Además de la plantilla html en sí, un componente puede tener el comportamiento y la lógica descritos en javascript, así como los estilos de alcance del componente.

No se requiere ninguna parte del componente, por lo tanto, el componente del contador puede consistir solo en la plantilla html del contador en sí. Para cambiar el valor de la variable de recuento , el controlador de clics utiliza el método incorporado del componente set () descrito en la documentación .

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


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")); 


▍Svelte


 <div> <button on:click="getData()">Get posts</button> {#each posts as {title, body}} <div> <h2><font color="#3AC1EF">{title}</font></h2> <p>{body}</p> </div> {/each} </div> <script> export default { methods: { getData() { fetch('https://jsonplaceholder.typicode.com/posts') .then(res => res.json()) .then(posts => this.set({ posts })); } } }; </script> 

→ Un ejemplo de trabajo.

▍Análisis


A diferencia de JSX, que, como una copia al carbón, se usa en los 3 marcos de la comparación original, y de hecho extiende el código de JavaScript con una sintaxis tipo html, Svelte usa características más familiares: incrustando código js y css en html usando < script> y <style> .

El script de componente exporta un objeto JS simple, dividido en secciones. La sección de métodos describe los métodos de componentes que se pueden utilizar a través de la instancia del componente y en los controladores de eventos. Entonces, cuando hace clic en el botón, se llama al método getData () , dentro del cual se solicitan los datos y al finalizar la operación, los datos simplemente se instalan en el estado del componente y se dibujan inmediatamente en la plantilla.

Tenga en cuenta el uso de la desestructuración del objeto de publicación (publicación) en cada paso de la iteración de la lista de publicación:

 {#each posts as {title, body}} 

Este truco evita la redundancia en plantillas como {post.title} y simplifica visualmente las plantillas con una entrada más corta {título} .

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


Reaccionar (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
 const TodoItem = ({ id, value, done, toggle }) = ( <li class={done ? "done" : ""} onclick={() => toggle(id)}> {value} </li> ); 


▍Svelte


 <li class="{done ? 'done' : ''}" on:click="set({done: !done})">{value}</li> 

→ Un ejemplo de trabajo.

▍Análisis


Aquí todo es bastante banal. Exponemos la clase css dependiendo del valor hecho y cambiamos este valor a lo opuesto cuando haces clic en un elemento de la lista.

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


Descargo de responsabilidad : a partir de ahora, decidí omitir la comparación con Hyperapp, porque de lo contrario las tablas serían simplemente ilegibles.

El evento
Reaccionar
Vue
Esbelto
Inicialización
constructor
beforeCreate,
creado
en el estado
Montaje
componentDidMount
beforeMount, montado
oncreate, onupdate
Actualización
componentDidUpdate
beforeUpdate, actualizado
onstate, onupdate
Desmontaje
componentWillUnmount
-ondestroy
Destrucción
-antes de destruir, destruido
-

▍Análisis


Svelte es extremadamente minimalista, incluso en términos de ganchos de ciclo de vida. Solo hay 4 ganchos:

  • onstate: se llama antes de que se cree el componente y cada cambio de estado antes de que se actualice el DOM.
  • oncreate: el momento en que se crea el componente se llama.
  • onupdate: se llama inmediatamente después del montaje en el DOM y cada cambio de estado después de actualizar el DOM.
  • ondestroy: se llama cuando el componente se destruye y se elimina del DOM.


Comparación de rendimiento del marco


Honestamente, no sé sobre qué comentar. Los puntos de referencia en sí mismos y la forma en que se ejecutan siempre generan mucha controversia, por lo que no creo que tenga sentido centrar innecesariamente la atención.
Sin embargo, todavía no tenemos otros datos.

▍Trabajar con mesas




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




▍Trabajando con memoria




▍Análisis


A juzgar por los números, Svelte es bastante rápido, "come" poca memoria (incluso porque no usa VirtualDOM), se inicia rápidamente y tiene un tamaño pequeño.

En general, no puedo decir que los resultados de los puntos de referencia de estos 3 marcos diferían drásticamente. Sin embargo, solo Svelte tiene una columna exclusivamente "verde", es decir es bastante bueno a la vez en todos los aspectos, lo que significa que está perfectamente equilibrado y no tiene distorsiones obvias ni en la velocidad ni en el consumo de memoria ni en otras métricas. En general, con él puede iniciar de forma segura cualquier proyecto, desde la web habitual, hasta dispositivos móviles, Smart TV y sistemas más exóticos.

imagen

Resumen


Svelte es una gran herramienta para construir componentes de casi cualquier aplicación web. Es tan poderoso como React, y aunque tiene una comunidad significativamente más pequeña, requiere menos esfuerzo para dominarlo. Es flexible, como Vue, mientras que es mucho más minimalista y verificado, ya que no trata de captar de inmediato todas las ideas del desarrollo web moderno.

Además, él es el único que utiliza el concepto de marcos en peligro de extinción . En otras palabras, no tiene un tiempo de ejecución específico que no sea el navegador en sí.

Las aplicaciones en él resultan rápidas, no requieren recursos y son de tamaño pequeño. Además, Svelte se puede usar "sin problemas" en aplicaciones escritas en otros marcos, sobre los cuales planeo escribir la próxima vez.

Si conoció por primera vez este maravilloso marco, podría estar interesado en leer otros artículos al respecto:

Marco JS que desaparece mágicamente
Autocompletar 1Kb
SvelteJS: Lanzamiento de la segunda versión

Si todavía tiene preguntas sobre Svelte , únase al canal de telegramas en ruso SvelteJS . Allí siempre puede hacer una pregunta y obtener consejos, conocer las últimas noticias y simplemente disfrutar chateando. Estaremos encantados de verte!

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


All Articles