技术选型,Vue和React的对比

1. MVVM和MVC

Vue是MVVM,React是MVC。

MVVM(Model-View-ViewModel)是在MVC(Model View Controller)的基础上,VM抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。

也就是说MVVM实现的是业务逻辑组件的重用,使开发更高效,结构更清晰,增加代码的复用性。

可以理解为MVVM是MVC的升级版。

虽然React不算一个完整的MVC框架,可以认为是MVC中的V(View),但是Vue的MVVM还是更面向未来一些。

2.  数据绑定

vue是双向绑定,react是单向绑定。

单向绑定的优点是相应的可以带来单向数据流,这样做的好处是所有状态变化都可以被记录、跟踪,状态变化通过手动调用通知,源头易追溯,没有“暗箱操作”。同时组件数据只有唯一的入口和出口,使得程序更直观更容易理解,有利于项目的可维护性。

但是Vue虽然是双向绑定,但是也是单向数据流,它的双向绑定只是一个语法糖,想看正经的双向绑定可以去看下Dva。

单向绑定的缺点则是代码量会相应的上升,数据的流转过程变长,从而出现很多类似的重复代码。同时由于对应用状态独立管理的严格要求(单一的全局store),在处理局部状态较多的场景时(如用户输入交互较多的“富表单型”应用),会显得冗余。

双向绑定可以在表单交互较多的场景下,会简化大量业务无关的代码。

我认为Vue的设计方案好一些,全局性数据流使用单向,局部性数据流使用双向。

3. 数据更新

3.1 React 更新流程

React 推崇 Immutable(不可变),通过重新render去发现和更新自身。

3.2 Vue 更新流程

Vue通过收集数据依赖去发现更新。

Vue很吸引人的就是它的响应式更新,Vue首次渲染触发data的getter,从而触发依赖收集,为对应的数据创建watcher,当数据发生更改的时候,setter被触发,然后通知各个watcher在下个tick的时候更新数据。

所以说,如果data中某些数据没有在模板template 中使用的话,更新这些数据的时候,是不会触发更新的。这样的设计非常好,没有在模版上用到的变量,当它的值发生变化时,不更新视图,相当于内置了React的shouldComponentUpdate。

3.3 更新比较

  • 获取数据更新的手段和更新的粒度不一样

Vue通过依赖收集,当数据更新时 ,Vue明确知道是哪些数据更新了,每个组件都有自己的渲渲染watcher,掌管当前组件的视图更新,所以可以精确地更新对应的组件,所以更新的粒度是组件级别的。

React会递归地把所有的子组件重新render一下,不管是不是更新的数据,此时,都是新的。然后通过 diff 算法 来决定更新哪部分的视图。所以,React 的更新粒度是一个整体。

  • 对更新数据是否需要渲染页面的处理不一样
  • 只有依赖收集的数据发生更新,Vue 才会去重新渲染页面
  • 只要数据有更新(setState,useState 等手段触发更新),都会去重新渲染页面 (可以使用shouldComponentUpdate/ PureComponent 改善)

Vue的文档里有一描述说,Vue是细粒度数据响应机制,所以说数据更新这一块,我认为Vue的设计方案好一些。

4. 性能对比

借用尤大大的一段话:

模板在性能这块吊打 tsx,在 IDE 支持抹平了的前提下用 tsx 本质上是在为了开发者的偏好牺牲用户体验的性能(性能没遇到瓶颈就无所谓) 这边自己不维护框架的人吐槽吐槽我也能理解,毕竟作为使用者只需要考虑自己爽不爽。作为维护者,Vue 的已有的用户习惯、生态和历史包袱摆在那里,能激进的程度是有限的,Vue 3 的大部分设计都是戴着镣铐跳舞,需要做很多折衷。如果真要激进还不如开个新项目,或者没人用的玩票项目,想怎么设计都可以。 组件泛型的问题也有不少人提出了,这个目前确实不行,但不表示以后不会有。 最后实话实说,所有前端里面像这个问题下面的类型体操运动员们毕竟是少数,绝大部分有 intellisense + 类型校验就满足需求了。真的对类型特别特别较真的用 React 也没什么不好,无非就是性能差点。

为什么模板性能吊打TSX?

tsx和vue template其实都是一样的模版语言,tsx最终也会被编译成createElement,模板被编译成render函数,所以本质上两者都有compile-time和runtime,但tsx的特殊性在于它本身是在ts语义下的,过于灵活导致优化无从下手。但是vue的模板得益于自身本来就是DSL,有自己的文法和语义,所以vue在模板的compile-time做了巨多的优化,比如提升不变的vnode,以及blocktree配合patchflag靶向更新,这些优化在最终的runtime上会把性能拉开不少。

DSL: 一种为特定领域设计的,具有受限表达性编程语言。

所以说Vue的性能是优于React的。

5. React Hooks和Vue Hooks

其实 React Hook 的限制非常多,比如官方文档中就专门有一个**章节**介绍它的限制:

  1. 不要在循环,条件或嵌套函数中调用 Hook
  2. 确保总是在你的 React 函数的最顶层调用他们。
  3. 遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。

而 Vue 带来的不同在于:

  1. 与 React Hooks 相同级别的逻辑组合功能,但有一些重要的区别。 与 React Hook 不同,setup函数仅被调用一次,这在性能上比较占优。

  2. 对调用顺序没什么要求,每次渲染中不会反复调用 Hook 函数,产生的的 GC 压力较小。

  3. 不必考虑几乎总是需要 useCallback 的问题,以防止传递函数prop给子组件的引用变化,导致无必要的重新渲染。

  4. React Hook 有臭名昭著的闭包陷阱问题,如果用户忘记传递正确的依赖项数组,useEffect 和 useMemo 可能会捕获过时的变量,这不受此问题的影响。 Vue 的自动依赖关系跟踪确保观察者和计算值始终正确无误。

  5. 不得不提一句,React Hook 里的「依赖」是需要你去手动声明的,而且官方提供了一个 eslint 插件,这个插件虽然大部分时候挺有用的,但是有时候也特别烦人,需要你手动加一行丑陋的注释去关闭它。

我们认可 React Hooks 的创造力,这也是 Vue-Composition-Api 的主要灵感来源。上面提到的问题确实存在于 React Hook 的设计中,我们注意到 Vue 的响应式模型恰好完美的解决了这些问题。

                                                                                                                          --- 来自ssh

Vue的组合式API刚出来的时候确实一看好像React Hooks,我也对它的.value进行了吐槽,

但是总体来说还是更偏向于Vue Hooks。

6. 写法

React的思路是all in js,通过js来生成html,所以设计了jsx,还有通过js来操作css,社区的styled-component、jss等,所以说React的写法感觉相对自由一些,逻辑正确老子想怎么写怎么写,对于我来说,我确实更偏向于React的写法。

Vue则是把html,css,js组合到一起,就像 Web 开发多年的传统开发方式一样, vue-loader会解析文件,提取每个语言块用各自的处理方式,vue有单文件组件(SFC),可以把html、css、js写到一个文件中,html提供了模板引擎来处理。Vue感觉是给你搭了一个框架,告诉你什么地方该写什么东西,你只要按照他的要求向里面填内容就可以了,没有React那么自由,但是上手难度简单了许多。而且因为SFC,一个组件的代码会看起来很长,维护起来很头痛。

7. 理念及设计

Vue 和 React 的核心差异,以及核心差异对后续设计产生的“不可逆”影响。

Vue 和 React 在 API 设计风格和哲学理念(甚至作者个人魅力)上的不同。

Vue 和 React 在工程化预编译构建阶段,AOT 和 JIT 优化的本质差异和设计。

这个层次的比较确实对我难度确实大,我也懒得去copy,下面是Lucas大佬的分析,可以去看一下,时空隧道

猜你喜欢

转载自juejin.im/post/7037365650251055134