React学习心得分享: React 对比 Vue
前言:一直以来,Vue 都是我的主力前端框架。从模板语法、响应式数据到组合式 API,Vue 的“开箱即用”和“保姆级体验”伴随我完成了许多项目。最近,我系统地学习了小满老师的 React Docs 文档,将 React 作为我的第二门前端框架正式纳入口袋。
虽然目前我刚刚学完整个教程、还没有在实际商业项目中完整踩过实战的坑,但这套体系化学习下来,我最大的感受就是:React 和 Vue 的底层世界观完全不同。
下面对照这份 React 文档的知识脉络(基础语法、编译工具、底层原理、组件体系、CSS 方案、Hooks 全家桶、路由与状态管理),结合我熟悉的 Vue,写下这份初学者视角的框架对比与心得笔记。
1. 入门与语法:模板指令 vs “一切皆是 JS”
打开文档的第一章,就是 TSX(JSX)语法。对于习惯了 Vue 模板语法的开发者来说,这是第一道冲击。
| 业务场景 | Vue (Template 语法糖) | React (TSX / JS 表达式) | 体验感受 |
|---|---|---|---|
| 数据插值 | {{ message }} | {message} | React 用单大括号,里面可以写任意合法的 JS 表达式。 |
| 条件渲染 | v-if="flag" / v-else | flag ? <A /> : <B /> 或 flag && <A /> | Vue 是指令化思维;React 完全靠原生 JS 的三元运算符和短路求值。 |
| 列表渲染 | v-for="item in list" :key="item.id" | list.map(item => <li key={item.id}>{item.name}</li>) | React 没有特定指令,就是原生数组的 .map()。 |
| 事件绑定 | @click="handleClick" | onClick={handleClick} | 驼峰命名,传函数引用。 |
| 类名绑定 | :class="{ active: isActive }" | className={isActive ? 'active' : ''} | React 中 class 是 JS 关键字,必须写 className;for 需写成 htmlFor。 |
学习感受:
- Vue 的感受是“规整”:Vue 给开发者设计好了各种指令(
v-if,v-for,v-model),模板结构清晰,HTML 该长什么样就是什么样。 - React 的感受是“自由”:TSX 根本不是模板,它本质上就是 JavaScript 语法扩展。不用记框架自创的指令语法,只要 JS 基础好,就可以随意用
if/else、map、filter来组装 UI。
2. 构建与编译工具:Babel / SWC vs Vue SFC Compiler
文档在“工具篇”特意讲解了 Babel 与 SWC。
- React 的转译本质:我们写的
<div className="box">Hello</div>,经由 Babel 或 SWC 转译后,本质上是变成React.createElement('div', { className: 'box' }, 'Hello')(或者新的_jsx('div', ...))。 - 对比 Vue:Vue 的核心是 SFC(单文件组件
.vue),由@vitejs/plugin-vue解析,将<template>编译为高效的 render 函数,并将<script>和<style>分离处理。
学习感受:
通过文档手写 Babel/SWC 转译示例后我才明白:React 的组件真的就是一个返回虚拟 DOM 对象的纯 JS 函数,它没有 Vue SFC 那么强的结构专属感。
3. 核心原理篇:不可逆的时间切片与细粒度响应式
文档中关于 VDOM、Fiber、Diff 以及 requestIdleCallback 的章节是我读得最过瘾、也最烧脑的部分。
① Fiber 架构与双缓存机制
- React 的痛点与解法:早期的 React 递归遍历 VDOM 树,如果组件树太深就会长期霸占主线程导致页面掉帧卡顿。于是 React 16 彻底重构为 Fiber 架构,把树状结构变成了链表结构,借助浏览器空闲调度(类似
requestIdleCallback)实现可中断、可恢复的异步更新(时间切片)。并通过“当前树 (current)”与“工作树 (workInProgress)”双缓存交替来提高渲染稳定性。 - Vue 的解法(靶向更新):Vue 根本不需要 Fiber 这种复杂的时间切片!因为 Vue 拥有基于 Proxy 的精准依赖收集。Vue 在编译时做了大量静态标记(PatchFlag、静态提升),数据变化时,直接精准定位到对应的组件或具体 DOM 节点进行打补丁,更新开销极小。
② Diff 算法差异
- React Diff:同层比较,仅支持向右移动单向比较,若 key 匹配但位置靠前,可能会引发多余的移动操作。
- Vue Diff:Vue 2 采用双端 Diff(头头、尾尾、头尾交叉对比),Vue 3 采用基于最长递增子序列的快速 Diff,在 DOM 移动次数的优化上更加极致。
4. 组件体系:单向流动的严谨与灵活
文档中的组件篇涵盖了组件通信、受控组件、Portal、Suspense 和 HOC(高阶组件)。
① 受控组件 vs v-model
这是初学 React 时最容易手忙脚乱的地方:
- Vue:一个
v-model="text"搞定双向绑定。 - React:必须显式声明为受控组件:
<input value={text} onChange={(e) => setText(e.target.value)} />② 插槽 vs children & Render Props
- Vue:拥有极其完善的插槽系统(默认插槽、具名插槽
<template #header>、作用域插槽)。 - React:默认内容直接通过
props.children获取;如果需要作用域插槽的效果,直接传一个函数即可(Render Props 模式:props.render(data)),纯 JS 函数传参,简单直接。
③ 传送组件与异步组件
- 传送组件:React 的
createPortal(JSX, domNode)对标 Vue 的<Teleport to="body">。 - 异步加载:React 的
lazy(() => import(...)) + <Suspense fallback={<Loading />} />对标 Vue 的defineAsyncComponent + <Suspense> (但是这部分我在Vue里面没怎么用过...)。
④ 高阶组件 (HOC)
React 拥有丰富的高阶组件文化(接收组件并返回增强后的新组件),而 Vue 社区在进入 Vue 3 后基本统一推崇 Composition API,极少使用 HOC, React在更多的Hooks支持下, HOC的使用场景也被大大压缩, 平时开发听小满说根本用不到。
5. CSS 方案:自由探索 vs 开箱即用
在 Vue 里,我们最习惯的写法是:
<style scoped>
.title { color: red; }
</style>scoped 属性通过 PostCSS 自动给 DOM 添加 data-v-xxx 属性选择器,干净又好用。
而在 React 文档中,CSS 方案是一场“百家争鸣”:
CSS Modules:文件命名为
index.module.css,像对象一样import styles from './index.module.css',通过className={styles.title}调用,生成哈希类名隔离, 说到底是没有Vue那种scoped隔离的痛。- CSS-in-JS(如 styled-components / emotion):把样式直接作为组件来写, Ant Design就是用的这种方式写的样式。
- Tailwind CSS:原子化 CSS,文档里重点推荐,由于写在
className里很自然,在 React 社区极为流行, 当然在Vue的圈子里面也极为的流行, 说到底就是极为的流行。
6. 核心重头戏:React Hooks 全家桶 vs Vue 组合式 API
读完整份文档,Hooks 是篇幅最大、也是和 Vue 3 Composition API 思想碰撞最激烈的部分。
① useState vs ref / reactive
- Vue:数据是“可变响应式代理”。
const count = ref(0)
count.value++ // 直接修改,Proxy 自动捕获并派发更新- React:强调不可变数据(Immutable)(很傻感觉,DX很不好,得用第三方useImmer去加强DX)。
const [count, setCount] = useState(0)
setCount(count + 1) // 必须显式调用 setter,不能直接 count = 1② useEffect vs watch / watchEffect / 生命周期
在 Vue 中,挂载、卸载、监听是各司其职的(onMounted、onUnmounted、watch)。
而在 React 中,文档把所有的“副作用”都归拢到了 useEffect 中:
- 依赖项传
[]:相当于onMounted,返回的清理函数相当于onUnmounted。 - 依赖项传
[count]:相当于watch(count, ...)。 - 文档还介绍了更细分的
useLayoutEffect(DOM 变更后、浏览器绘制前同步执行,防闪烁)以及useInsertionEffect(专为 CSS-in-JS 插入样式设计)。
③ useMemo & useCallback vs computed(最大的心智负担差异!)
这是我认为 Vue 转 React 最需要适应的核心区别:
- 在 Vue 3 中:组件的
<script setup>只在初始化时执行一次。computed自动收集依赖,数据变了才重新计算,完全不需要手动管理函数的引用。 - 在 React 中:每次状态变化,整个函数组件就会从头到尾重新执行一遍!
- 组件内的普通函数每次渲染都会重新声明新的引用,导致传递给子组件时引发子组件无意义的重渲染;
- 因此必须显式使用
useCallback缓存函数引用,使用useMemo缓存计算密集型结果!
好在后面的Next中已经可以开启Rect Compiler减少这种心智负担, 不然真的会死人的😢
④ useRef 的双重身份
在 Vue 中 ref 既用来做响应式数据,又用来绑定 DOM。
在 React 中:
- 获取 DOM 节点:
<div ref={domRef} />; - 保存跨渲染周期的可变数据:
useRef(initialValue)改变.current不会触发组件重新渲染,.current可以得到绑定的DOM的值
⑤ 并发特性 Hooks(useTransition & useDeferredValue)
文档中还深入到了 React 18 的并发特性:
useTransition:把某些不紧急的状态更新(如复杂的列表过滤)标记为低优先级过渡任务,防止输入框打字卡顿。useDeferredValue:延迟派生某个值的更新。
这展示了 React 面对重型计算和交互优先级调度时的强悍能力。
7. 路由与全局状态管理:React Router 与 Zustand
① 路由篇:React Router v7 vs Vue Router
- Vue Router:中心化路由配置,配合内置的
<router-view>,导航守卫(beforeEach)非常直观。 - React Router (v7):有loader和action两个路由的行为, 这个是跟Vue有很大区别的地方, 可以在页面上要Get请求获取数据的地方提前在路由的loader中执行, 页面中需要执行Post提交表单的地方执行路由action里面的逻辑, 提交表单数据, 然后回到页面还能自动执行一次loader获取一次新的数据, 这一点让开发的体感很好, 还有各种Hooks
useNavigate(), useParams(), useLoaderData(), useActionData()。 - React Router还有很多模式, 但是实际上感觉还是使用跟Vue一样 的数据路由模式更好理解。
② 状态管理篇:Zustand vs Pinia
文档在全局状态管理中选择了极其轻巧优雅的 Zustand,而不是笨重的传统 Redux:
import { create } from 'zustand'
const useStore = create((set) => ({
bears: 0,
increase: () => set((state) => ({ bears: state.bears + 1 })),
}))- 对比 Vue 的 Pinia,两者的开发体验惊人地相似:都摒弃了 Mutation 的概念,体积轻巧,支持直接解构 Hook 使用。
- 但 Zustand 在内部依然严格遵循 React 的不可变合并思想,写起来非常纯粹。
- Zustand 还有自定义各种middleware和官方推荐的第三方的middleware就比如Immer, 这个就很好使用, 能不用管React什么傻x的不可变数据原则, 虽然底层还是保留了这个原则。
总结:我的学习感想
学完这整套 React 文档,如果用一句话总结两者的区别:
Vue 像一辆配置自动档位的车:响应式自动追踪、模板指令丰富、Scoped CSS 开箱即用,框架替你处理好了绝大多数优化细节,上手平滑、开发体验极度舒适。 就很自动, 而且三剑客不分离,代码美观易懂 ,新手上手很快,跟着官方走准没错,生态方面差一点。
React 则像一辆纯手动挡的车:没有魔法,纯粹靠原汁原味的 JavaScript 驱动。它的单向数据流、不可变思想和 Fiber 架构非常严谨,但也正因如此,很多优化得自己去调用Hooks。三剑客合家,代码不美观。但是React的生态丰富, 社区热情度更高,有很多UI库和Hooks库,人人都可以处理React麻烦的点,欣欣向荣。
作为刚刚学完理论知识、尚未经历大型项目实战的前端学习者,我不知道这些说的对不对,但是这就是我个人的感受。学习React我认为在如今是必须,无论是你为了ReactNative的跨端带来的便利,还是为了阅读更多React,Next的优秀项目,React都是作为前端的必需品。在Ai时代下,学习一个框架变得更加的简单,不懂的知识能问Ai快速的获取,代码也从一定要能写出来,更加的倾向于能看懂,知道逻辑,技术栈的选择感觉也更偏向于Ai能不能把这个技术的代码给写好,毕竟现在都是Ai写代码。