前言:react和vue选哪个
前端框架经过十多年的争奇斗艳百花齐放,经历了JSP
、jQuery
、Ember
、Angular
、React
、Vue
等,如今逐渐进入稳定发展阶段,剩下了2个最具影响力的框架:React
和Vue
。
新建项目时,面对React
和Vue
主流框架,相信很多小伙伴会遇到如下疑问,框架选择犹豫不决:
- 公司团队经常用什么我就用什么吗?
- 这2个框架各有什么优点和缺点?
- 近几年Vue3、React18 相继更新升级,我要在团队里做第一个吃螃蟹的人的吗?
…
以上问题咱们暂且放一放,先来从”团队适用性、业务适用性、技术生态“3个方面全方位细致地了解React和Vue框架,最后该选哪个框架自有答案~~❤️
选型对象
React18.x 和 Vue3.x 版本
对比考虑的因素
1. 团队适用性
-
以开发者角度来看:
如果你是才入职到新环境的开发,并且接手的是一个成熟的项目,处于正常迭代阶段,那不要想着颠覆团队已有技术栈,技术栈切换相当于重构,需要很多人力和时间成本。
-
以项目负责人角度来看:
如果你是项目负责人,在新建项目时候需要做技术选型,那么在对比技术生态的同时,还需要考虑团队开发成员对技术栈的熟悉程度,选择大多数人都熟悉的技术栈,有助于提升项目产出效率和质量;但如果大多数人都选择尝试新技术,并且有信心面对各种挑战,也可以考虑新的技术栈。
-
结合历史项目来看:
在做技术选型的时候,还应着重调研参考公司历史项目使用的技术栈。如果历史项目做技术栈切换重构,需要有相应的开发、测试、产品、运维等人力投入,因此会带来巨大的不可控风险,如果恰逢业务方等着要业务需求交付的话,上下游工作都会被影响。所以历史项目重构需谨慎考虑!!!
2. 业务适用性
React
适用于构建大型、复杂的单页应用,比如to B 管理系统等Vue2.x
options API 适用于中小型的单页应用,但Vue3.x
composition API 和 Typescript 的加持也可以开发大型项目,比如to C 移动端应用等
以上结论,是通过对比React、Vue的技术框架特点、优缺点总结的,下面我们从技术生态角度来具体对比2种框架看看~
3. 技术生态
概述简介
react
React
,起源Facebook内部项目,整体采用函数式编程,使用 JSX(JavaScript 语法扩展)开发灵活度较高,可用于构建用户界面应用(Web应用程序和原生应用)的JavaScript框架。
特性:
- 函数式编程:使用纯函数稳定无副作用(输入相同,输出结果一定相同),使代码可复用性和可维护性提升。React16后出现的hooks,更进一步提升可复用性。
- 响应式(单向数据流):数据流自顶向下,从父节点传递到子节点,如果顶层(父级)某个props改变了,React会重新渲染所有子节点。
- 高效(Virtual DOM):Virtual DOM,最大限度地减少DOM操作。
- JSX 灵活:使用JSX语法构建组件化代码,React组件有2种:函数组件(无状态组件,可继承)、class组件(有状态组件)。
- TS支持完善:Tsx 的开发体验完全来自于 TS 专门针对 Jsx 制定的一整套推导机制。
vue
Vue
,是渐进式JavaScript框架,它基于HTML、CSS和JavaScript构建,并提供了一套声明式、组件化的编程模型,用于开发用户界面应用。
特性:
- 易上手:基于标准HTML、CSS和JavaScript三件套风格,简单易上手。
- 渐进式:无论学习还是实际开发,周边生态都是可选的不是必需的,当需要用到路由,引入vue-router;系统业务复杂需要用到状态管理,引入vuex/pinia。
- 响应式(双向绑定):vue2底层使用Object.defineProperty对数据监听实现响应式处理,vue3则使用Proxy做代理。
- 声明式(vue3):vue3升级更新,出现composition API,使用声明式函数编程,提升了可维护性。高可复用的逻辑功能则抽离为hooks,和React hooks有异曲同工之妙。
- TS支持良好:官方的建议,用
<script setup lang="ts">
+vscode
+volar
,一样能获得非常好的 TS 体验。- 性能优异(中小型项目):具体比对参数详见“性能对比”部分。
设计原理
react
React
框架设计为单向数据流传递,数据通过 state 状态管理。当调用 setState 修改数据会更新渲染整个 vdom,期间需要大量计算。所以为了确保渲染性能,框架内部使用 reconcile 调和器将 vdom 转换为 fiber(双链表),且设置允许打断渲染机制,由 schedule 任务调度器实现。完整的渲染过程如下图所示:
vue
Vue
和 React
框架设计原理比较雷同的就是,引入Virtual DOM,本质也是为了减少DOM操作,实现数据响应式,其他就不太相同了。Vue基于HTML、CSS和JavaScript模板开发的,因此整个渲染过程,需要渲染器、编译器和观察者,如下图所示:
性能对比
对比说明
- 本章节性能对比的数据皆有据可查,对比仅覆盖了些常见应用场景,但未能覆盖全局场景。
- 对比数据(可点击查看),可根据条件筛选框架对比的结果
- 测试对比的对象:Vue v3.2.47 和 React v18.2.0
- 测试使用浏览器及设配系统:Chrome 113 – OSX
对比内容
- 这里主要是数据量较大的列表操作,对比维度如下:
- 创建列表
- 替换所有行
- 局部更新
- 选择行
- 交换行
- 删除行
- 创建多行
- 追加多行
- 删除多行
结果可查看下图,绿色表示操作所需时间更短,黄色表示操作时间所需较长,红色表示操作所需时间很长。
上图结论:可以看到Vue在数据量大的列表操作场景中近乎完胜,尤其是交换行的情况,Vue更是大幅领先。
- 启动指标,主要从以下几个方面对比:
- 加载时长:主要指标是TTI(Time to Interactive),指从页面开始加载到页面可进行交互的时长,TTI值越小,代表用户可以更早地操作页面,体验就越好
- 主线程工作时间:包含样式、布局、执行逻辑等
- 网络传输字节数:值加载页面中所有资源的成本
上图结论:还是Vue相对优秀
- 内存分配(以MB为单位),对比维度如下:
- 页面加载的内存使用情况
- 运行内存,添加 1000 行后的内存使用情况
- 每 10 行点击更新 5 次后的内存使用情况
- 创建/清除 1000 行 5 次后的内存使用情况
- 创建 10000 行后的内存使用情况
上图结论:还是Vue胜出
思考
以上性能对比是以1000行数据为基准的,如果数据量更庞大呢,5w或10w行,甚至50w行,数据会有变化吗?结论会有变化吗?
就本人来看,虽然以上性能对比React落于下风,但从React Fiber架构来看,大数据量的虚拟DOM比对时,React是具有优势的,此架构可以通过 Schedule 调度器设置任务优先级,尽可能地减少主线程阻塞,对用户体验的感知是相对友好的。
使用层面
JSX vs Template
React
采用 JSX
更为灵活,将HTML、CSS全都融入JS,属于 all in js。React中,渲染逻辑和标签共存于同一个地方——组件。
Vue
则使用 Template
模版语法,和传统HTML、CSS、JS分离开发比较类似,虽然灵活度不如JSX,模版语法语法穷举所有原生JS能力,但对于新手更为友好。在Vue3框架中,从模版层面做了静态优化,对静态模板做标记,从而提升节点diff效率,使得框架渲染性能提升。
生命周期
react
- 初始化挂载时(4个):
constructor
:初始化组件state、事件处理(比如绑定节流、防抖函数)getDerivedStateFromProps
:通过比较nextProps和prevState,更新state,同时也方便处理为null的情况render
:将jsx转化为React Element元素。componentDidMount
:组件挂载到真实DOM,这时可以获取真实DOM节点。
- 更新时(5个):
getDerivedStateFromProps
:更新时,将props映射到state,具体处理同初始化。shouldComponentUpdate
:传入新的props、新的state和新的context,返回值判断是否继续执行 render 函数。render
:同初始化。getSnapshotBeforeUpdate
:执行在commit阶段,commit分为 Before Mutation(DOM修改前),Mutation(DOM修改)、Layout(DOM修改后),该钩子函数发生在 Before Mutation 阶段,可用来处理组件更新前的逻辑。componentDidUpdate
:组件更新后DOM操作。
- 卸载时(1个):
componentWillUnmount
:组件卸载,解除事件监听。
vue
- 初始化阶段(3个)
setup
:合并beforeCreate、created生命周期钩子,用做初始化数据和事件。onBeforeMount
(载入前):编译模版准备渲染,这时可以用来初始化数据,比如发起ajax请求。onMounted
(载入后):上面编译准备好的html内容,完成render,渲染生成真实DOM,这时候数据、真实DOM、事件已挂载处理,可以获取真实DOM做交互逻辑。
- 更新阶段(2个)
onBeforeUpdate
(更新前):组件或实例的数据更改,会触发该生命周期钩子,发生在vdom更新渲染之前。onUpdated
(更新后):数据更新,已完成重新渲染。这时候可以获取更新后的DOM。
- 卸载阶段(2个)
onBeforeUnmount
(销毁前):组件销毁之前,可以用来清除事件绑定,比如清除定时器。onUnmounted
(销毁后):调用后,所有的事件监听被移除,子组件被卸载。
组件通信
React
和 Vue
组件通信有些许相似,具体有3种通信方式雷同,如下所示:
React
- 父组件->子组件通信:props
- 子组件->父组件通信:回调函数
- 跨层级通信:provide/inject
Vue
- 父组件->子组件通信:props
- 子组件->父组件通信:$emit 事件
- 跨层级通信:context
样式处理
React
- className(嵌入式)
- inline style(内联)
- CSS Modules(外链)
- 引入第三方依赖处理
- styled-components
- classnames
- 预处理器
Vue
- class + style scoped(嵌入式)
- inline style(内联)
- CSS Module(外链)
- 预处理器
React、Vue样式处理使用层面虽然有些差异,但本质都是CSS处理,3种样式表引入方式都支持:行内样式表(行内式/内联)、内部样式表(嵌入式)、外部样式表(链接式)。
事件处理(onClick vs @click)
React
React
元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
function Form() {
function handleSubmit(e) {
e.preventDefault(); console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
Vue
基本事件
Vue
使用v-on指令(简写为@)监听DOM事件,并在事件触发时执行对应JavaScript。
// 1. v-on
v-on:click="handler"
// 2. @
@click="handler"
事件处理器(handler)有2种:
- 内联事件处理器
const count = ref(0)
<button @click="count++">Add 1</button>
<p>Count is: {{ count }}</p>
- 方法事件处理器
const name = ref('Vue.js')
function greet(event) {
alert(`Hello ${name.value}!`)
// `event` 是 DOM 原生事件
if (event) {
alert(event.target.tagName)
}
}
<button @click="greet">Greet</button>
自定义事件
使用 v-on
指令监听自定义事件,父组件绑定事件名(建议kebab-case
命名),子组件通过 $emit 触发调用,如下示例:
父组件:
<MyComponent @my-event="handleThis" />
<!-- 内联声明 -->
<MyComponent @my-event="handleThis(123)" />
子组件:
this.$emit('my-event’, 'haha')
周边配套
React
路由管理
- React-router
状态管理
- Redux:基础的状态管理库
- React-Redux:Redux插件库,用来简化
- Redux-thunk:处理异步的中间件
- Redux-saga:内部基于generator,也是用来处理异步的中间件
- Mobx:使用简单,修改数据本身即可实现视图的更新
UI框架
- ant-design
- arco-design
- chakra-ui
- MUI
- …
Vue
路由管理
- vue-router
状态管理
- vuex
- pinia
UI框架
- element-plus
- vant
- …
跨端处理
React
App
在跨 App 界的一哥是 ReactNative,以下简称 RN,因为本人没有亲自体验过,所以不做过多阐述,但是鉴于 RN 是2015年4月问世,时间不短,并且也有足够的团队使用,目前看来在前端跨端的领域成熟度已经相当高了。
小程序
对React支持度最好的当然是 Taro 了,一直在持续迭代中,也有来自京东凹凸实验室的背书,拥有较为稳定的产品和活跃社区,开发者可以大胆尝试,Taro 3 可以支持转换到 H5、ReactNative 以及任意小程序平台。
Vue
App
原生App开发,对Vue支持度相对友好的有 Weex、Vue Native、Capacitor等框架。
小程序
uni-app 对Vue前端开发人员比较友好,学习成本比较低,uni-app是基于vue.js的。其次,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。
兼容性
- PC端:
React
和Vue
均不支持IE8以下,对于个别浏览器兼容模式使用IE内核也可能是不支持的,具体要看使用的内核版本。尤其Vue3直接放弃对IE的支持。 - H5端:
React
没什么兼容问题,但Vue3响应式底层使用Proxy来实现,Proxy在IOS端最低支持10版本,polyfill处理兼容问题不能完全兼顾,因为是基于Object.defineProperty。所以业务环境对IOS9有兼容需求的,就不要轻易尝试了。
总结
到了文末,关于 React
和 Vue
的选型,我们来做个总结,具体如下:
- 在选型前,我们首要看团队适用性(综合考虑历史因素和团队现状),以及切换技术栈的开发成本和增加上下游合作的时间成本。
- 再者还要充分考虑框架的兼容性,如果不满足业务需求,再优秀的框架也要pass掉。
- 然后了解框架原理,全面地对比React、Vue框架的性能特性、使用难易、周边配套、跨端处理等方面。
最后,不论 React
还是 Vue
,都是相当优秀的框架,框架底层同样实现了Virtual DOM减少DOM操作,有着不错的性能,同时还有着声明式编程的特性,方便地维护代码。再者各自都拥有着活跃的社区和周边,在跨端上也有着不错的支持。所以,选哪个框架生态,就根据各自公司业务背景和需求来做抉择吧!!
参考:
krausest.github.io/js-framewor… (性能对比)
caniuse.com (查看兼容性)