一张图看懂react/vue区别

757 阅读5分钟

理性讨论 欢迎指正错误 重点是学习交流

react和vue作为前端领域两个巨头,做的都是从数据渲染到UI的事情,下面用一张图从渲染角度来看下两者是如何实现的,两者有什么区别?以及为什么react有fiber有时间切片而vue没有?为什么react在开发中要手动实现优化工作而vue不需要?本人react使用3年多,Vue使用2年多。结合自己的实际体验,下面是我画的一张简图。

一图胜千言

截屏2023-07-15 下午7.11.57.png

如图可以明显的看到两者以vdom为分界线,根据自身的特点做了不同的优化思路。

为什么react需要fiber时间分片而vue没有:

时间分片旨在让应用进行CPU大量计算时也能与用户交互,而vue因为采用模板的方式,语法相对固定,本身通过静态模板分析做了很多编译时优化,提升了vdom的diff性能,再加上响应式系统的加持下更新范围进一步被缩小,避免了cpu大量计算的场景,而react因为jsx的开发方式,甚至完全兼容js的语法特性,导致其动态性过于强,不运行根本不知道vdom其结构是怎样的,是否发生了变化。所以必须在每次更新时都重新运行,做很多的计算以保证结果的正确性。
尤大之前也在一篇帖子下面回答过这个问题:

在 Web 应用中,「可中断式更新」主要是由大量 CPU 计算加上复杂 DOM 操作引起的。时间分片旨在让应用在 CPU 进行大量计算时也能与用户交互,但时间分片只能对大量 CPU 计算进行优化,无法优化复杂 DOM 操作,因为要确保用户正在操作的界面是最新的状态才行。 因此,我们可以考虑两种不同的可中断式更新的场景:
1. CPU 计算量不大,但 DOM 操作非常复杂(比如说你向页面中插入了十万个节点)。这种场景下不管你做不做时间分片,页面都会很卡。
2. CPU 计算量非常大。理论上时间分片在这种场景里会有较大收益,但是人机交互研究表明,除了动画之外,大部分用户不会觉得 10 毫秒和 100 毫秒有很大区别。 也就是说,时间分片只在 CPU 需要连续计算 100 毫秒以上的情况下才有较大收益。有意思的地方就出现了,在 React 经常会出现 100 毫秒以上的计算量,因为
1. Fiber 架构的复杂性导致 React 的虚拟 DOM 协调效率较低,这是系统性的问题。
2. React 使用 JSX 导致它的渲染效率比 template 低,因为 template 很容易做静态分析和优化。
3. React Hooks 将大部分组件树的优化 API 暴露给开发者,开发者很多时候需要手动调用 useMemo 来优化渲染效率。(译注:这里省略一些例子)这意味着 React 应用默认就有 render 过多的问题。 更严重的是,这些优化在 React 里很难自动化,因为
1. 这些优化要求开发者正确设置依赖数组
2. 盲目添加 useMemo 会导致应该 render 的没 render。 很不幸,大部分开发者都很懒,不会在每个地方都加上优化,因此大部分 React 应用都会有大量的没必要的 CPU 计算工作。 对比较而言,Vue 解决了上述问题:
1. Vue 的架构里没有时间分片,也就没有 Fiber,因此简单了很多,这使得渲染可以更快。
2. Vue 通过分析 template、简化协调过程,做了大量的 AOT 优化,性能测试结果表明大部分的 DOM 内容有 80% 属于静态内容,因此 Vue 3 的协调速度比 Svelte 快,花费的时间比 React 的 1/10 还少。
3. 通过数据响应式追踪,Vue 可以做到组件树级别的优化,比如把插槽编译为函数以避免 children 的变化引发 re-render,比如自动缓存内联事件处理函数以避免 re-render。Vue 3 可以做到在不借助开发者的任何手动优化的情况下,防止子组件在非必要的情况下 re-render。这意味着同样一次更新,React 应用可能要 re-render 多个组件,而 Vue 应用很可能只 re-render 一个组件。
因此,在默认情况下,Vue 3 应用会比 React 应用少花费很多 CPU 时间,因而遇到 CPU 连续计算时间超过 100 毫秒的机会相当少,除非是极端情况。但大部分极端情况是 DOM 操作过于复杂,而不是 CPU 计算量太大。 另外,时间分片,或者说并发模式,给 React 带来了另外一个问题:React 需要对所有更新任务进行调度和调和,这导致 React 还需要搞定任务优先级、任务失效处理、re-entry 等任务,这会使 React 变得更复杂,进而让源码的体积膨胀。就算 React 把 Suspense、Tree-shaking 等优化都加上,Vue 3 的运行时体积也只有 React + ReactDOM 的 1/4。 注意我并不是说并发模式是个馊主意,并发模式确实对处理某些问题提供了有意思的新途径(尤其是在协调异步状态转换时 coordinating async state transitions),但是为此而实现时间分片是否值得,还需要再三权衡,至少现在不值得 Vue 3 这样做。

为什么react在开发中要手动实现优化工作而vue不需要

这个问题上面也有答案,因为react本身无法分辨出组件是否需要更新,所以需要开发者手动设置。Vue可以通过响应式追踪到。

参考:

react.dev/learn

cn.vuejs.org/guide/extra…

mp.weixin.qq.com/s/wclLaG4dT…