阅读 23960

为什么我们选择Vue,而不选React(译)

最近Qwintry团队积极地把Vue.js作为了他们的前端框架,并且在所有的新旧项目中使用它,包括:

  • 过去qwintry.com的Drupal系统 (qwintry.com)

  • 我们的新项目,完全重写了qwintry.com分支

  • 一个用Yii2 构建的B2B系统 (logistics.qwintry.com)

  • 我们所有的小项目和外部拓展项目(大部分是php和node作为后台的)

世界上有大约被50W人使用Qwintry。我们用我们的软件经营着两个货仓(一个在美国,一个在德国)。在美国,我们是最大的邮件代理之一,我们的用户和货运通道主要集中在东欧和中东。其实,我们主要是帮助人们节约一些航运的费用,让他们更方便的在网上购买美国的商品。并且我们利用我们的信息和物流系统,帮人们找到最好的性价比的商品。

这是我们在用户门前的包裹。

我们拥有庞大的代码库,基本都是用PHP和JS构建的。

在我们分别用React、Vue.js、Angular 2这些现代框架来构建我们的“用户计算器”之后,经过比较,我们决定使用Vue.js。

我对React的看法

当我们在讨论选择前端框架的时候,React在JS世界的膨胀,导致了它现在很可能已经成为JS开发者默认的选择。

我用React开发了一些SPA的应用,也做过一些动态的组件。我也在IOS下玩弄过RN + Redux。我觉得React对JS来说有一个伟大的出发点就是状态机,它给人们展现了函数式编程的优势。我觉得RN的野心是庞大的,它改变了原生开发的世界。

对React的不足之处的个人见解

以一种纯净的、不变的、稳定的机制来控制状态

别误会,我很欣赏用纯函数和简单的render的方式控制状态,毫无疑问,这在真实环境的生命周期中是一个很好的形式。我要讨论的是其它的一些点。

我想,当你的团队有超过1000个开发人员的时候,这种纯净的、严格的模式可能是很有必要的。但也只有当你想把你自己的语法加入到你写的静态规范的代码的时候才是必要的,或者你是一个从Haskell转到JS的开发者。但大多数的开发团队一般都是比Facebook小得多的开发团队。

恶心的JSX

我懂我懂,它仅仅就只是一个特别的js语法。本来我们的设计兼前端仔只需要去专注于每一行HTML的elements就好,然而他们现在写代码就像在吃shi。让设计师使用JSX写React组件是非常恶心的事情,因为JSX的可读性太差了。不能在html代码块里写一些简单的判断语句,请别相信那些盲目的React粉丝告诉你,你不会需要写这个,你只需要写三元就好。我敢保证,在实际开发过程中,你仍然需要读写一堆HTML和JS的混合代码,即使他们后来被编译成纯JS。

    {items.map(item =>
  • {item.name} )} 复制代码

    大量的开发者(曾经包括我)都觉得这是一个由特定限制的语法,这将会帮助你写出更加模块化的代码,因为你不得不把你许多辅助方法也放入你的render函数里,就像这家伙的建议:
    stackoverflow.com/a/38231866/…

    也正是因为JSX的写法,所以你不得不把15行的html代码分割到三个组件中(每个组件5行html)去。

    不要觉得这是可以让你成为优秀开发者的一个好方法,因为其实你只是不得不像上面那样编码罢了。

    这里有一些场景:

    当你在写一个复杂组件(一个你可能并不会把它发布在你的github上的组件)的时候,你为了完成实际业务目标,你会拆分你的组件,然后组装成一个更完善的大组件,因为JSX的数据规范可能会让你的数据流溢出。但,我的意思不是说小组件不好或者效率不高。

    你应该清晰的意识到你把你的代码分离到别的组件是为了保持代码的可读性和可复用性。但你也应该知道,把你的代码组件化是因为每个组件他们有自己的逻辑实体,被分离后的组件有自己内部的属性,(而且建议如果只有两三个 if 的时候建议写三元表达式)。每次你创建了一个新的组件,都会消耗一些内存和一点点数据流(也可能更多),因为你需要从完成模块业务的思路(当你确定你已经记住了当前组件的状态,并且你只需要添加一个html就能运行当前组件)切换到管理业务(管理组件)的思路上来。这样你就可以去分离组件,开始思考新组件的属性,新组件如何去适应状态,如何设计回调函数等等。

    事实上,因为在一个不必要的地方,强行权衡组件的模块化过大或是过小的时候,会减慢你的编码速度。在我看来,提前决定模块化的方案就相当于提前决定了最佳实践方案。

    对于我和我的团队来说,代码的可读性是最重要的,但是代码的趣味性也一样很重要。试想,当你想要生效你的计算器插件需要用到6个组件,这样的编码并不有趣。并且在很多情况下,一些插件代码的维护、拓展或可视化测试,都要在好几个文件或函数里跳来跳去,并且需要检查每个被分离的html的小包是否正确运行。再次声明,我不支持写一个巨大的组件,我支持的是用组件去代替日复一日的微组件开发。这样比较符合常识。

    用表单和Redux编码将会让你一整天都在归类

    React是基于一个纯净的单向数据流的框架,记得吗?这就是为什么 LinkedStateMixin 双向绑定变得流行。现在,你必须创建10个函数获得10个input里面的值。在这些函数中,有80%会包括一个this.setState() 的函数调用,或者如果是Redux的action回调(那样的话,你不得不再创建另外10个常量来匹配这10个input)。我猜,你一定想如果能靠脑补就自动生成这些关联代码就好了,但是我目前还没有发现哪个ide可以提供这样的插件。

    为什么我们不得不归类这么多?因为双向绑定被一些大企业的大佬们认为是很危险的。我也承认使用双向绑定的数据流进行编码,有可能可读性不是那么好,但是这些担心大部分都是因为Angular 1的双向绑定带来的负面影响,而且这可能也不是双向绑定最大的值得担忧的地方。

    现在让我为你展示一个快速编辑器组件,这个组件是我最近用Vue.js为我们的Drupal网站构建的。

    我没有贴出我的源码的原因显而易见,但是用Vue编码的过程是有趣的,并且代码的可读性很强。

    现在,我很确信,如果要我使用React完成上图中的操作,就需要为每一个input创建一个单独的函数,来达到控制一个挂件的目的,这样做,并不会让我感到快乐。

    Redux 听上去就像是冗余的同义词,现在也很容易的找到一些开发者,他们的职责是将React转型成Angular。这么做也只是因为想要让数据实现双向绑定。我的第一个要点是“1 关于纯净”。似乎很多聪明的人会让他们的代码库变得比他们的工作更有价值(我猜,当你的工作没有截止日期的时候,一定很爽)。

    过多的依赖

    React需要被babel编译,如果没有一连串的npm包,你的react项目将会寸步难行,所以先用es5进行开发。最简单的应用开发也会需要基于一些官方的React依赖包,这些包在node_modules里面,大约有75MB。

    这不是在批判,这些依赖这么多,更多原因是由于js本身的原因,而不是React的原因。但是这些综合因素加起来,使得使用React开发变得很累。

    Angular 1:太自由反而不是好事

    ng1曾经也是一个伟大的框架它与React完全相反,它的代码可阅读性更好,它允许你快速上手,在刚刚开始的1K行代码中,你的确感受到了许多的乐趣,之后它就会让你一直写出糟糕的代码。你很可能在大量的指令,scope和双向数据流中迷失方向,它们贯穿于你所有的应用中难以维护。因为是难以维护的,所以让你们新加入的开发者去维护旧系统,更是让人拒绝的。

    为什么会这样呢?

    ng1创造于2009年,那时候的前端应用都还很简单,没有人想到之后会有这么多状态管理的问题。你不应该去责备他们,他们只是想用一些新理念超越Backbone,并且写更少的代码。

    Angular 2

    为了构造一个hello world的应用,然后找到项目的入口文件,你需要使用Typescript并且编译它们才可以开始工作。这实际上还是要在我真正开始工作之前,所做的一些规范。依我看来,开发ng2的人尝试去构建一个更优雅的框架打败React,而不是尝试去构建一个能解决大多数用户问题的框架。可能我这个想法是错的,我对于ng2也还没有太多的经验,因为我们仅仅是用它为我们的货仓做了一套用户的计算器系统,用来测试它的框架性能。这有篇写的很好的对比其他框架的文章,ng2的确是很棒的框架,这篇文章里也与Vue进行了许多的对比。

    Vue.js

    简单的说,Vue.js 就是我等待已久的框架(我将会讨论Vue2,一个比第一版改进了很多的框架,并且也在最近发布了稳定的版本)。对我来说,Vue的优雅和简洁能够让我更加专注于业务代码。Vue可以说是2007年的jQuery之后,又一个给JS世界带了巨大改变的框架了。

    如果你想看看Vue的人气,你会发现不仅仅只有我是看好Vue的:www.timqian.com/star-histor…

    Vue.js能成为2016年里高速发展的JS架构之一,我认为它的发展不仅仅是靠粉丝的支持,更是因为一些权威组织的学术支持和肯定。

    Laravel也把Vue.js添加到它的核心思想中去,这是一个值得关注的事情。

    Vue.js的特点

    Vue.js在代码的可读性、可维护性和趣味性的方面的处理可谓是会心一击。如果你看过Vue的文档指南,你会马上发现,这个框架将比React和Angular 1 带来更好的编程体验。

    对比React,React是一个以组件为基础的框架,每个组件实例有自己的方法、属性、顺着组件层级的单向数据流、函数调用、虚拟dom、和状态管理。

    对比Angular 1,Angular 1 更像是一个有着优秀语法的模板,并且有你一定会需要的双向数据绑定(在单个组件内)。

    Vue.js是一个很容易起步的框架,这在我们的团队中已经得到了印证。它不需要强制的基于任何编译环境,所以它能很容易地和你的历史遗留代码结合,并且能马上用Vue的代码改善历史用jQuery编码时的问题。

    快速得到正确的结果

    无论是在html,还是在js中使用框架,Vue.js都是一个很容上手的框架。它让你在操作一个复杂的模板的时候,你可以专注你的业务。并且即使这个模板非常大,也能有很强的可读性。在这个时候,你就能更方便地根据你的业务逻辑处理好的你的代码逻辑。如果你想重构模板并且拆分它们成更小的组件,你也可以从刚开始的大模板中更清晰地看到整个应用的关联关系。

    从我的开发经验来看,这种开发模式与我用React开发的时候有着巨大的差别:我能从中节约好多时间。在用React的时候,你不得不在第一次编码的时候就把你的组件拆分成一个个的小组件,或者你可以直接把你原来的代码直接删了。在使用React的过程中,当你编程编到一半,不得不因为应用逻辑改变而去改变你的数据流的时候,你很可能会因为无法清晰的看到完整数据流,导致了你花费很多时间去一次次地修正你的属性和状态,并且还要一次次重构你那些超级小的组件(可能之后根本用不到的小组件)。

    在Vue.js中操作表单也是轻而易举的。双向绑定的数据流是Vue的一大亮点。即使是在复杂的场景下也不会带来任何问题,虽然第一眼看到watcher可能会让人想起Angular 1。当你拆分你的组件时,你总是能通过回调来单向传输需要改变的数据。

    如果你想要使用一些预处理的工具,比如PostCSS、ES6,可以点这里。在Vue2里面,写一个公共组件已经成为拓展Vue的默认方式了。顺便值得一提的是,在组件内编写css,是一种看起来很棒的体验,它能够减少传统css的命名的层级问题,就像BEM一样。

    Vue.js有简单的、高效的状态管理机制,比如用data()和props(),他们能在实际场景的使用过程中发挥很大的作用。并且能够通过Vuex更好的分离状态管理,帮助我们更有效的管理状态(Vuex在我看来是一个和React中的Mobx差不多的状态管理工具,一款把状态操作和状态分离的管理工具)。

    VueJS的一些问题

    1、最大的问题就是:对运行过程的模板错误并没有提示。这一点和Angular 1 很像。Vue.js会在你的开发过程中提供很多有用的警告,比如,当你错误的修改props或错误定义data()的时候,会有警告提示。但模板运行过程中的错误是Vue的一个弱点,特别是多次的堆栈处理并没有什么用,这和Vue的内部方法有关。

    2、Vue.js 2 还很新,它还没有稳定的组件社区,现有的很多组件也都是基于Vue.js 1 构建的。并且对刚入门的人来说,可能很难从github的一些组件仓库里看出,这个库使用的是Vue的哪个版本。但其实,这个问题也好解决,因为你几乎可以不用使用任何的附加库,就能够完成一个复杂的Vue的项目。你可能只会需要一些ajax请求的库。如果你并不关心同构应用的话,vue-resource是一个不错的选择,否则请选择axios。并且vue-router也是一个经常被使用的库,一个能够提供路由的很棒的库。

    3、中文文档也在很多社区上都能找到,这很正常,因为Vue.js在中国也很流行(作者也能够说中文)。

    4、是一个人写了一个项目吗?这实际上算不上是一个问题,但是也有人会在意。尤小右是一个曾在Google和Meteor工作的男人,是他创造了Vue。Laravel曾经也是只有一个人在写的项目,但现在也已经取得了巨大的成就,所以你无从得知一个人写出来的项目有多强大。

    使用Vue.js开发Drupal

    免责声明:我们没有打算很快的在Qwintry中使用Drupal 8,当我们切换到更快更便捷的PHP和NODE框架的时候,我们的历史遗留代码仍然使用Drupal 7。

    因为我们是用Drupal 7 构建我们的历史系统(qwintry.com),因此对新框架的测试对我们来说很重要。我一点也不为我们冗余的历史代码感到自豪,但是它确实稳定运行着,并为我们盈利。所以我们维护它,改善它,并为它增加功能。在这里我罗列了一些我已经用Vue + Drupal构建好的功能:

    为复杂的订单业务设计的系统。包括给用户生成订单、对购买项的快速编辑。包括在加载的时候加载一些基本的JSON数据和保存一些数据结点。这些都没什么特别的,只是一些简单的数据回调。

    两套REST的系统。我们的用户不用在不同的网站上重复登录,我们为特殊用户快速检查身份信息。这些操作都是基于我们的用户管理系统。

    我知道有很多后端开发者仍然停留在2010年的时代,并且也知道Drupal 7 的核心就是Ajax请求系统。

    我能够想象,尝试利用多步Ajax请求来重构核心功能,是多么的复杂。之后想要去维护这些代码更是难上加难。没错,就是Drupal里面的ctools_wizard_multistep_form() 这个函数,你可以看看它的ajax是如何操作的

    并且,这些Drupal开发者都在抓紧时间学习很多流行的UI框架,但是他们可能比较害怕学习流行的JS框架。我一年前也是这样。现在让我来告诉你,你很难找到更好的方式来改善你的接口,但是现在使用了Vue.js就不一样了。你可以根据drupal_add_js把你的请求地址加入到模板中,然后就可以去放松了。你一定会震惊,客户端能够在你设置的钩子的回调里,这么容易的就拿到了纯净的JSON,表单也是一样的,这么方便的操作都是因为使用了Vue。

    配合Yii2使用Vue.js

    一个有趣的事,Yii也是一个中国boy做的 -- 薛强。所以你可能会发现Yii + Vue这样的技术栈的发音并不是很难,因为这也是一个中国人创造的技术 :)

    在我们新版本的网站Qwintry.com(还没上线)的项目里,我们选择使用Yii2,我相信它是PHP框架里最好最快之一。虽然它不像Laravel那样流行,毕竟Laravel现在已经席卷了PHP世界了,但是我们在使用Yii2开发的过程中仍然很开心(虽然我们也时不时的去看看Laravel的发展,毕竟这个框架还是相当不错的)。

    我们在逐渐减少使用Yii2来生成html 模板,后台把注意力集中在REST上,生成JSON给我们用Vue构建的客户端使用。我们的动态记录模型几乎都是先确定好API,然后再构造数据。

    相应的,我们也有很规范接口设计,这就是我们为什么要花费大量的时间去构建好我们的接口文档,即使这些文档只是我们内部使用。

    我们的后端是用PHP7和最新的MySQL进行开发的,使用Yii2返回数据的响应时间和使用Node返回数据的响应时间没什么差别(我是说15-20ms左右的差别)。所以Yii2是符合我们要求的。我们可以想象用户使用我们的Drupal项目的时候,速度会比原来提升10-20倍。同时,它也支持所有老版本的PHP库,能够让我们很方便地利用人工去更好的维护我们的代码库。

    所以,Yii2 + Vue.js的开发搭配能够发挥出很大效用,并且能够让你的工作变得更愉悦。

    我们也在我们的很多其他项目上使用Vue.js。

    结论

    这三个月以来我们每天都在各种项目中写着Vue.js,让我们受益匪浅。三个月不用写后端代码,却全是JS的世界。让我们对这个世界拭目以待 :)

    我希望在未来的16-24个月内,Vue能成为一个不可替代的JS框架。如果小右能让这个框架向着正确的方向发展,Vue至少可以成为一些前、后端团队核心框架。我认为,即使到了2017年,React依然还会是JS世界的主要框架,特别是,如果RN能够更好地管理自己,并保持它以往的节奏去改善自己的话。

    原文地址: Why we chose Vue.js over React


    本文对你有帮助?欢迎扫码加入前端学习小组微信群:

    关注下面的标签,发现更多相似文章
    评论