JS框架比较:React,Vue和Hyperapp

该材料的作者(我们今天将其翻译发表) 认为 HyperappReactVue这样的Web框架的值得注意的替代品。 他说这一说法的原因是,他发现Hyperapp比这两个框架更易于学习。 他的想法遭到了批评,因为它似乎完全是基于他的观点,并且这种方法根本无法给其他框架展示其优势的机会。 本文旨在通过简单的示例演示Hyperap,React和Vue的功能,并根据其测试结果进行客观分析。



例1:柜台申请


计数器应用程序的实现可能是反应式编程中最常用的示例之一。 这是非常简单易懂的:

  • 我们需要变量count ,它将存储计数器的值。
  • 需要两种方法来增加和减少变量count
  • 需要一种机制来显示存储在count的值并将其呈现给用户。
  • 需要将两个按钮绑定到适当的方法,以允许用户对count变量进行操作。

这是使用有关框架的此示例的实现。

▍反应


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

ueVue


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

perHyperapp


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

▍分析


如果您不熟悉这些框架,甚至不熟悉其中的至少一个,那么在这里,您可能会遇到一些难以理解的事情。 因此,让我们分析一下这段代码。

  • 当使用所有三个框架时,在应用程序代码的开头有import命令。
  • React使用面向对象的范例。 这将为Counter组件创建一个类。 Vue也是如此。 在这里,将创建Vue类的新实例,并将信息传递给它。 最后,Hyperapp使用功能范式,使用独立的实体viewstateactions
  • 如果我们谈论变量count ,那么在React中它是在组件构造函数中初始化的,而在Vue和Hyperapp中,它分别是datastate对象的一个​​属性。
  • 如果进一步研究这些应用程序,我们可以看到React和Vue使用非常相似的方法与count变量进行交互。 在React中,要更改应用程序的状态,请使用从React.Component继承的setState方法。 在Vue中, this.count的值直接更改。 Hyperapp方法是使用ES6箭头函数语法编写的。 在所讨论的框架中,他是唯一使用此框架的框架,因为React和Vue被迫在其方法内部使用this关键字。 另一方面,Hyperapp方法要求将它们作为参数传递给具有应用程序状态的对象。 这意味着它们很可能在各种情况下都可以重用。
  • 在这三个示例中,负责将数据输出到页面的应用程序部分看起来几乎相同。 Vue的独特之处在于,使用此框架时,必须将h函数传递给呈现子系统。 Hyperapp使用onclick而不是onclick ,并且由于在每个框架中存储应用程序状态的方式的特殊性,此处对count变量的访问不同于React和Vue。
  • 最后,所有三个框架都使用对#app元素的绑定。 在每个操作中,此操作均以不同方式执行。 应当注意,在Vue中,此操作看起来最简单,最容易理解,并且使开发人员可以使用元素选择器而不是元素本身进行更灵活的设计。

▍结论


如果直接比较使用这三个框架解决相同问题的代码,那么事实证明,Hyperapp用于实现计数器应用程序,需要最少的代码行数,并且这是唯一使用功能性方法的框架。 但是,使用Vue编写的代码量,如果计算字符数,结果会少一点,并且在其中使用元素选择器看起来非常好。 React应用程序的代码似乎是最长的,但这并不意味着它比为与其他分析框架一起工作而编写的代码更难理解。

示例2:使用异步代码


实际上,您可能必须处理异步代码。 最常见的异步操作之一是向某个API发送请求。 就本示例而言, 使用JSONPlaceholder API ,其中包含条件数据并列出发布。 这是我们在这里要做的事情:

  • 我们在应用程序状态下保存要发布的数组。
  • 我们使用适当的方法fetch()调用,指示所需的URL,等待数据到达,解析接收到的JSON代码(对象数组),最后通过将接收到的数据写入其中来更新posts变量。
  • 我们在页面上显示一个按钮,该按钮调用加载出版物列表的方法。
  • 使用键列出帖子中的posts

考虑实现上述操作方案的代码。

▍反应


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

ueVue


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

perHyperapp


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

▍分析


让我们分析这段代码,并比较三个调查的框架。

  • 与前面的示例一样,在所有三个框架中,存储应用程序的状态,输出数据以及连接到页面元素都非常相似。 在这里,我们已经提到了相同的差异。
  • 使用fetch()函数下载数据是一个相当简单的操作;它在所有框架中都能正常工作。 但是,这里的主要区别是Hyperapp支持执行异步操作的方式与其他框架有所不同。 代替直接在异步动作中修改状态,此动作调用另一个同步动作,该动作接收数据并将其转换为合适的格式。 这使应用程序核心更具功能性,更适合分解为可能适合重用的小部分。 此外,这种方法还有助于避免嵌套回调固有的一些问题,这些问题可能在此类情况下出现。
  • 如果我们讨论代码的大小,那么Hyperapp应用程序再次需要更少的代码行来达到相同的目标,但是Vue代码看起来更短,并且如果您计算代码中的字符数,它比其他选项还要短。

▍结论


在所有框架中执行异步操作都变得同样简单。 Hyperapp可能会导致开发人员在使用异步操作时编写更多的功能性和模块化代码,但是其他两个框架也出色地完成了他们的任务,因此,这给开发人员提供了选择的机会。

示例3:待办事项应用程序的列表项组件


待办事项应用程序可能是反应式编程中最著名的示例。 显然,几乎所有现有框架都实现了类似的功能。 在这里,我们将不会实现整个应用程序。 相反,我们将重点放在一个简单的无状态组件上,以研究所研究框架用于创建适合重用的小型Web应用程序构建块的可能性。

考虑使用研究的框架来实现组件。 但是,在此示例中,我们将通过考虑以功能样式编写的React组件来扩展所考虑的代码选项。

▍反应(实用风格)


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

▍反应


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

ueVue


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

perHyperapp


请注意,Hyperapp也使用功能样式。

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

▍分析


  • 就编码模式的使用而言,React是最灵活的框架。 它支持功能组件以及设计为类的组件。 此外,React以其标准形式还支持Hyperapp组件。
  • Hyperapp还支持功能性的React组件。 这意味着在使用Hyperapp和React时,有足够的实验空间。
  • Vue在该测试中排名倒数第二。 它具有一个相当奇怪的语法,即使对于那些熟悉React或Hyperapp的人也很难立即理解。
  • 如果我们讨论代码的长度,那么所有示例的大小都非常相似。 这里唯一需要注意的是,React上的代码在其中一个选项中比在另一个选项中更为庞大。

▍结论


习惯Vue需要一些时间,因为它的模板与其他两个框架的模板略有不同。 React非常灵活,它支持用于创建组件的各种方法。 同时,Hyperapp中的一切都非常简单,并且还与React兼容,React允许您在项目的某个阶段更改框架。

组件生命周期方法的比较


影响框架选择的另一个重要考虑因素是它支持的组件生命周期事件,您可以订阅这些事件,并可以根据开发人员的需求进行处理。 这是基于对所研究系统的API进行分析的表格。
大事记
反应
Vue
超级应用程式
初始化
建设者
beforeCreate,已创建
--
安装方式
comoinentDidMount
beforeMount,已安装
创建
更新资料
componentDidUpdate
beforeUpdate,已更新
更新
正在卸载
componentWillUnmount
--移除
毁灭
--销毁前,销毁
毁灭

▍分析


通过分析此表,可以了解以下内容:

  • 大多数生命周期挂钩都在Vue中。 在他们的帮助下,程序员有机会在调用相应事件之前或之后处理组件发生的所有事情。 这对于管理复杂的组件可能会派上用场。
  • React和Hyperapp的生命周期挂钩非常相似,尽管React结合了在组件的卸载和销毁过程中发生的事件的处理,而Hyperapp还可用于创建和安装组件的事件。 它们都为开发人员提供了处理生命周期事件的足够数量的可能性。
  • Vue不处理unmount事件(据分析框架API可以理解的那样),而是依靠与破坏组件相关的钩子。 React不处理组件终止事件,仅允许处理组件卸载事件。 Hyperapp不提供钩子来处理组件创建事件,而是完全依赖于挂载事件。 根据您的需求和经验,在设计应用程序时应考虑这些差异,并考虑处理组件生命周期事件的可能性。

▍结论


通常,应该指出的是,用于处理在组件生命周期内发生的事件的方法支持所有框架。 这些方法将解决许多问题。 这三个框架都为所有类型的事件提供了挂钩,但是它们之间存在细微的差别,其来源可以是框架的内部功能及其实现上的差异。 也许Vue在这一领域领先于其他系统,提供了更详细的事件处理系统,使您可以在事件发生之前或之后处理生命周期事件。

框架性能比较


除了使用框架的便利性和用于框架的编程技术外,许多开发人员还严重关注框架的性能,尤其是对于相当复杂的应用程序。 js-framework-benchmark项目是有关各种框架性能的有价值信息来源。

因此,请看一下React,Vue和Hyperapp的测试结果。

tables使用表格


这是使用表的框架的测试结果。 表格单元格中的指示符对应于操作持续时间±标准偏差。 将获得的指标除以最佳指标的结果显示在括号中。


分析方法


  • 不使用键(非键)进行数据输出的操作要比使用键(键)的操作快得多。
  • 在所考虑的全部六个选项中,最快的是使用React而不使用键的选项,这在所有测试中均显示出令人印象深刻的性能。
  • 如果在使用键时比较Vue和React,则Vue会有一点优势。 同时,如果您在不使用键的变体中比较React和Vue,则Vue的性能将显着低于React。
  • 从结果中可以看出,Vue和Hyperapp在测试中遇到了一些困难,其中执行了表的部分更新,React很好地展示了自己,这可能是由于旨在加速此类更新的一些优化所致。操作。

▍加载,启动,代码大小


这是一张表格,其中包含与框架启动速度,大小,使用主线程有关的指标的研究结果。


分析方法


  • 事实证明,Hyperapp代码是所研究框架中最小的代码。 React和Vue代码的大小大致相同。
  • Hyperapp需要最少的启动时间。 当然,这样做的原因是框架代码的尺寸小和设计其API的简约方法。
  • 就启动框架而言,Vue比React快一点。

memory处理内存


现在考虑测试内存分配的结果。


分析方法


  • 就内存消耗而言,Hyperapp是最不需要的框架。
  • 通常,应该指出的是,所有框架都不会消耗太多内存。 这表明它们在现代计算机上的工作原理大致相同。

▍结论


如果在开发项目时需要达到最高性能,则首先应了解所开发的应用程序类型,其次要清楚地确定该应用程序的需求。 如果将所有三个框架的性能分析结合在一起,您会感觉到Vue和React更适合于更复杂的应用程序,而Hyperapp在需要处理较少数据(需要尽可能快地启动)的较小规模的应用程序中更胜一筹,以及可能需要在最快的计算机上工作的人。

但是,值得记住的是,在某种平均情况下,此处使用的性能测试与实际情况相去甚远。 因此,在实际项目中对它们进行了测试和比较之后,您可以看到其他结果。

附加说明


应当注意,比较Web框架可能类似于将苹果与橘子进行比较。 以下是有关React,Vue和Hyperapp的其他一些注意事项,这些注意事项在为项目选择特定框架时可能会有用:

  • React绕过了一个问题,即相邻的JSX元素必须包装在父元素中,引入了片段的概念-允许您对一组后代元素进行分组的元素,而无需向DOM添加其他节点。
  • React为开发人员提供了更高阶的组件 ,而Vue使用mixins重用了组件功能。
  • Vue更充分地利用了责任分离的概念,使用模板分离了应用程序的结构和功能。
  • 与React和Vue相比,Hyperapp看起来像一个提供较低级别API的系统。 Hyperapp应用程序的代码变短了,它提供了很大的灵活性,这在开发人员可能希望通过微调和研究其内部机制来解决它的情况下很有用。

总结


该材料的作者认为,如果您读到这一点,那么您已经了解了本文研究的哪些框架最适合您的需求。 最后,我们并不是在讨论哪个框架是最好的,而是在哪个框架中最能展示自己的框架。 结果,我们可以得出以下一般结论:

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

! -?


, - 10% :)

Source: https://habr.com/ru/post/zh-CN417483/


All Articles