Vue vs React 对照手册
前端面试必备 · 逐项对比 · 深入理解两大框架差异
01 框架哲学对比
VueReact
Vue — 渐进式框架
约定优于配置 开箱即用
Template-first 模板优先
渐进式 按需引入功能
响应式驱动 自动依赖追踪
React — UI 库
一切皆JS UI = f(state)
JSX-first JS 中写模板
组合模式 自由组装生态
单向数据流 显式更新
Vue 理念
对比维度
React 理念
渐进式框架,核心 + 可选工具链
定位
UI 渲染库,生态自由组合
模板 + 指令系统,关注点分离
视图表达
JSX,JS 和 UI 融合
Proxy 自动追踪,开发者无感
响应式
setState 手动触发,显式更新
SFC 单文件组件 (.vue)
组件格式
函数组件 (.jsx/.tsx)
官方维护全家桶,开箱即用
生态策略
社区驱动,百花齐放
02 响应式 vs 单向数据流
数据流对比图
Vue — Proxy 响应式
修改数据 → Proxy 拦截 → 自动触发视图更新
开发者无需手动触发
开发者无需手动触发
React — setState 驱动
调用 setState → 调度更新 → Virtual DOM Diff → 最小化更新
开发者必须显式调用 setState
开发者必须显式调用 setState
计数器示例对比
Vue 3 — Composition API
<script setup>
import { ref, computed } from 'vue'
const count = ref(0)
const double = computed(() => count.value * 2)
function increment() {
count.value++ // 自动触发更新,无需手动
}
</script>
<template>
<p>计数: {{ count }}</p>
<p>双倍: {{ double }}</p>
<button @click="increment">+1</button>
</template>
React — Hooks
import { useState, useMemo } from 'react'
function Counter() {
const [count, setCount] = useState(0)
const double = useMemo(
() => count * 2, [count]
)
function increment() {
setCount(c => c + 1) // 显式调用 setter
}
return (
<>
<p>计数: {count}</p>
<p>双倍: {double}</p>
<button onClick={increment}>+1</button>
</>
)
}
Vue 响应式
对比点
React 状态管理
ref() / reactive() 声明,直接赋值触发更新声明方式
useState() 返回 [value, setter],必须调用 setterProxy 自动追踪依赖,精确更新
更新机制
setState → 整组件 re-render → Virtual DOM Diff
computed() 自动缓存派生计算
useMemo() 手动声明依赖数组默认细粒度更新,无需手动优化
性能优化
需 React.memo / useMemo / useCallback 手动优化
03 模板语法 vs JSX — 10 大常见模式
核心差异:Vue 使用 HTML 模板 + 指令(v-if / v-for),React 使用 JSX(三元表达式 / map),模板更声明式,JSX更灵活。
① 条件渲染
Vue
<div v-if="isLoggedIn">欢迎回来</div>
<div v-else>请先登录</div>
<!-- v-show: 切换 display -->
<p v-show="visible">仅切换显示/隐藏</p>
React
<div>{isLoggedIn ? '欢迎回来' : '请先登录'}</div>
{/* && 短路写法 */}
{isLoggedIn && <div>欢迎回来</div>}
② 列表渲染
Vue
<ul>
<li v-for="item in list"
:key="item.id">
{{ item.name }}
</li>
</ul>
React
<ul>
{list.map(item => (
<li key={item.id}>
{item.name}
</li>
))}
</ul>
③ 双向绑定 / 表单
Vue
<!-- v-model 语法糖 -->
<input v-model="text" />
<input v-model.number="age" />
<!-- 等价于 -->
<input
:value="text"
@input="text = $event.target.value"
/>
React
{/* 受控组件,手动绑定 */}
<input
value={text}
onChange={e => setText(e.target.value)}
/>
{/* 数字转换 */}
<input
value={age}
onChange={e => setAge(Number(e.target.value))}
/>
④ 事件处理
Vue
<button @click="handleClick">点击</button>
<button @click="handleClick(item.id)">
传参
</button>
<input @keyup.enter="submit" />
React
<button onClick={handleClick}>点击</button>
<button onClick handleClick(item.id)}>
传参
</button>
<input onKeyDown e.key === 'Enter' && submit()} />
⑤ 动态属性绑定
Vue
<img :src="imgUrl" :alt="title" />
<div :class="{ active: isActive, 'text-bold': isBold }">
<div :style="{ color: fontColor, fontSize: size + 'px' }">
React
<img src={imgUrl} alt={title} />
<div className={`${isActive ? 'active' : ''} ${isBold ? 'text-bold' : ''}`}>
<div style={{ color: fontColor, fontSize: size + 'px' }}>
⑥ 计算属性
Vue
const fullName = computed(() =>
firstName.value + ' ' + lastName.value
)
// 模板中直接用 {{ fullName }}
// 自动缓存,依赖不变不重算
React
const fullName = useMemo(() =>
firstName + ' ' + lastName
, [firstName, lastName])
// JSX 中直接用 {fullName}
// 需手动声明依赖数组
⑦ 插槽 / 子内容
Vue
<!-- 父组件 -->
<Card>
<template #header>标题</template>
<template #default>内容</template>
<template #footer>底部</template>
</Card>
<!-- 子组件 Card.vue -->
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
React
{/* 父组件 */}
<Card
header={<h2>标题</h2>}
footer={<p>底部</p>}
>
内容
</Card>
{/* 子组件 Card */}
function Card({ header, footer, children }) {
return (
<>{header}{children}{footer}</>
)
}
⑧ 侦听器 / 副作用
Vue
watch(count, (newVal, oldVal) => {
console.log(newVal)
})
// 立即执行
watchEffect(() => {
fetchData(keyword.value)
})
React
useEffect(() => {
console.log(count)
}, [count])
// 每次渲染都执行
useEffect(() => {
fetchData(keyword)
}) // 无依赖数组
⑨ 模板引用 (Refs)
Vue
<input ref="inputRef" />
const inputRef = ref(null)
onMounted(() => {
inputRef.value.focus()
})
React
const inputRef = useRef(null)
<input ref={inputRef} />
useEffect(() => {
inputRef.current.focus()
}, [])
⑩ 组件定义
Vue
<!-- UserCard.vue -->
<script setup lang="ts">
defineProps<{ name: string; age: number }>()
const emit = defineEmits<{
(e: 'click', id: number): void
}>()
</script>
<template>
<div @click="emit('click', 1)">
{{ name }} / {{ age }}
</div>
</template>
React
// UserCard.tsx
interface Props {
name: string; age: number
onClick: (id: number) => void
}
function UserCard({ name, age, onClick }: Props) {
return (
<div onClick onClick(1)}>
{name} / {age}
</div>
)
}
export default UserCard
04 组件通信对照
Vue 方式
通信模式
React 方式
Props / Emit
defineProps 接收父组件数据defineEmits 向父组件发事件
// 子组件
const props = defineProps(['msg'])
const emit = defineEmits(['update'])
emit('update', newValue)
父子通信
↓ ↓ ↓
↓ ↓ ↓
Props / Callback
Props 传递数据和回调函数
子组件调用回调 → 通知父组件
Props 传递数据和回调函数
子组件调用回调 → 通知父组件
// 子组件
function Child({ msg, onUpdate }) {
onUpdate(newValue)
}
Provide / Inject
祖先
后代
祖先
provide('key', value)后代
inject('key')
// 祖先
provide('theme', 'dark')
// 后代
const theme = inject('theme')
跨层级
↓ ↓ ↓
↓ ↓ ↓
Context
createContext 创建上下文useContext 消费上下文
const Ctx = createContext('light')
// 祖先
<Ctx.Provider value="dark">
// 后代
const theme = useContext(Ctx)
Pinia / Vuex
全局状态管理,组件外可使用
全局状态管理,组件外可使用
defineStore → useStore
const useUser = defineStore('user', () => {
const name = ref('张三')
return { name }
})
全局状态
↓ ↓ ↓
↓ ↓ ↓
Redux / Zustand
Redux: reducer + dispatch
Zustand: 更轻量的 Hooks API
Redux: reducer + dispatch
Zustand: 更轻量的 Hooks API
// Zustand
const useStore = create((set) => ({
name: '张三',
setName: (n) => set({ name: n })
}))
EventBus / mitt
Vue 3 推荐使用 mitt 库
任意组件间事件通信
Vue 3 推荐使用 mitt 库
任意组件间事件通信
import mitt from 'mitt'
const bus = mitt()
bus.emit('refresh', data)
bus.on('refresh', handler)
任意组件
↓ ↓ ↓
↓ ↓ ↓
Custom Events / 状态提升
React 不推荐全局事件总线
通常状态提升到最近公共祖先
React 不推荐全局事件总线
通常状态提升到最近公共祖先
// 状态提升到公共父组件
function Parent() {
const [data, setData] = useState()
return <>
<A onSend={setData} />
<B data={data} />
</>
}
05 生命周期对照
核心转换公式:Vue 3 Composition API 的生命周期钩子几乎可以一一映射到 React 的
useEffect,但心智模型不同 — Vue 是钩子驱动,React 是依赖驱动。
生命周期时间线对照
Vue 3 生命周期
setup() — 组件初始化(Composition API 入口)onBeforeMount() — 挂载前,DOM 未就绪onMounted() — 挂载完成,可访问 DOMonBeforeUpdate() — 响应式数据变化,DOM 更新前onUpdated() — DOM 更新完成onBeforeUnmount() — 卸载前,清理资源onUnmounted() — 卸载完成onErrorCaptured() — 捕获后代错误React Hooks 等价
函数体执行 — 每次渲染都运行
useEffect — 无直接对应(少用)useEffect(() => {}, []) — 空依赖 = 仅挂载时执行useEffect 清理函数 — 更新前执行上一次的 cleanupuseEffect(() => {}, [deps]) — 依赖变化时执行useEffect 的 return cleanup — 卸载前执行组件函数不再执行 = 已卸载
ErrorBoundary 类组件 — getDerivedStateFromError对照代码示例
Vue 3 生命周期
import {
onMounted,
onUpdated,
onUnmounted
} from 'vue'
onMounted(() => {
console.log('组件已挂载')
// 获取 DOM、发请求、绑定事件
})
onUpdated(() => {
console.log('组件已更新')
})
onUnmounted(() => {
console.log('组件已卸载')
// 清理定时器、取消订阅
})
React Hooks 等价
import { useEffect } from 'react'
// ≈ onMounted + onUnmounted
useEffect(() => {
console.log('组件已挂载')
return () => {
console.log('组件将卸载')
// 清理定时器、取消订阅
}
}, []) // 空依赖 = 仅挂载/卸载
// ≈ onUpdated
useEffect(() => {
console.log('依赖变化,已更新')
}, [dep1, dep2]) // 依赖变化时执行
Vue
阶段
React
setup()创建
函数体(每次渲染执行)
onMounted()挂载
useEffect(() => {}, [])onUpdated()更新
useEffect(() => {}, [deps])onUnmounted()卸载
useEffect 的 return 清理函数watch() / watchEffect()侦听
useEffect() (依赖数组控制)nextTick()下一帧
flushSync() 或 queueMicrotask
06 常用生态对照表
Vue 生态
功能领域
React 生态
Vue Router
官方路由,支持守卫、动态路由
官方路由,支持守卫、动态路由
路由
React Router
声明式路由,v6 推荐 Hooks
声明式路由,v6 推荐 Hooks
Pinia
组合式 API,轻量直观,TS 友好
组合式 API,轻量直观,TS 友好
状态管理
Redux Toolkit / Zustand
RTK 标准化 / Zustand 极简
RTK 标准化 / Zustand 极简
Element Plus
企业级 UI,国内主流
企业级 UI,国内主流
UI 组件库
Ant Design
蚂蚁出品,全球广泛使用
蚂蚁出品,全球广泛使用
VeeValidate
声明式表单校验
声明式表单校验
表单
React Hook Form
非受控模式,性能优秀
非受控模式,性能优秀
Axios
HTTP 客户端,拦截器灵活
HTTP 客户端,拦截器灵活
HTTP 请求
Axios / SWR
Axios 或 SWR 数据缓存方案
Axios 或 SWR 数据缓存方案
Vite (官方)
极速构建,Vue 官方推荐
极速构建,Vue 官方推荐
构建工具
Vite / CRA
Vite 或 Create React App
Vite 或 Create React App
Nuxt.js
SSR/SSG 全栈框架
SSR/SSG 全栈框架
SSR 框架
Next.js
SSR/SSG/ISR,生态最成熟
SSR/SSG/ISR,生态最成熟
Vitest
Vite 原生测试框架
Vite 原生测试框架
测试
Jest
最流行的 JS 测试框架
最流行的 JS 测试框架
UniApp
一套代码多端运行
一套代码多端运行
移动端
React Native
原生渲染,性能接近原生
原生渲染,性能接近原生
07 性能优化对照
面试关键点:Vue 默认细粒度更新(Proxy 精确追踪),React 默认整组件 re-render(需手动优化)。理解这个根本差异是面试加分项。
Vue 优化
优化策略
React 优化
computed
const filtered = computed(() =>
list.filter(fn)
)
自动缓存,依赖不变不重算
缓存计算
useMemo
const filtered = useMemo(() =>
list.filter(fn)
, [list])
手动声明依赖数组
shallowRef / shallowReactive
const state = shallowRef(bigObj)
// 仅追踪 .value 变化
// 不深层追踪内部属性
浅层响应
React.memo
const MyComp = React.memo(
function MyComp(props) {
// props 不变则跳过渲染
}
)
v-once / v-memo
<!-- 仅渲染一次 -->
<div v-once>{{ msg }}</div>
<!-- 条件缓存 -->
<div v-memo="[item.id]">
渲染控制
useCallback
const handler = useCallback(
() => doSomething(id),
[id]
)
// 稳定函数引用
// 避免 child 不必要的 re-render
KeepAlive
<KeepAlive :include="['CompA']">
<component :is="current" />
</KeepAlive>
组件缓存
手动实现 / 第三方
// React 无内置 KeepAlive
// 使用 display:none 切换
// 或使用 react-activation 库
{showA && <CompA />}
{showB && <CompB />}
defineAsyncComponent
const Async = defineAsyncComponent(
() => import('./Heavy.vue')
)
懒加载
React.lazy + Suspense
const Lazy = React.lazy(
() => import('./Heavy')
)
<Suspense fallback={<Loading />}>
<Lazy />
</Suspense>
08 选型决策树
需要 React Native 移动端开发?
→
选 React(代码共享 + 原生渲染)
团队 HTML/CSS 背景为主?
→
选 Vue(模板语法更直观)
需要快速原型 / 中小型项目?
→
选 Vue(开箱即用,配置少)
大型团队 / 需要最大灵活性?
→
选 React(生态丰富,社区大)
国内企业 / 中文生态优先?
→
选 Vue(国内社区活跃,Element 生态完善)
需要 SSR 且优先考虑生态成熟度?
→
选 React + Next.js
TypeScript 深度集成需求?
→
选 Vue 3(TS 支持一流)
现有项目已使用某个框架?
→
保持一致,不轻易切换
选 Vue 的理由
+ 学习曲线平缓,上手快
+ 模板语法直观,关注点分离
+ 中文文档完善,国内生态丰富
+ 响应式自动化,开发体验好
+ SFC 单文件组件,结构清晰
+ Vite 官方推荐,构建极速
+ Pinia 轻量优雅,TS 支持好
选 React 的理由
+ 社区最大,解决方案最丰富
+ React Native 共享移动端开发
+ 函数式编程思想,灵活性高
+ Next.js SSR 方案最成熟
+ 大厂广泛使用(Meta、Netflix)
+ 人才市场更大
+ JSX 赋予完全的 JS 能力
09 面试高频对比题 (15 道)
使用提示:点击题目展开答案。面试时建议先说核心差异,再结合场景举例,最后总结各自优劣。
1 Vue 和 React 的核心区别是什么?▶
核心区别在响应式模型和视图表达:
1. 响应式:Vue 使用 Proxy 自动追踪依赖,修改数据自动更新视图;React 使用 setState 手动触发更新,通过 Virtual DOM Diff 计算最小变更。
2. 视图:Vue 使用模板 + 指令(v-if/v-for),关注点分离;React 使用 JSX,在 JS 中写 UI,一切皆 JavaScript。
3. 定位:Vue 是渐进式框架,官方维护全家桶;React 是 UI 库,生态由社区驱动。
4. 组件格式:Vue 是 SFC 单文件组件;React 是函数组件 + Hooks。
1. 响应式:Vue 使用 Proxy 自动追踪依赖,修改数据自动更新视图;React 使用 setState 手动触发更新,通过 Virtual DOM Diff 计算最小变更。
2. 视图:Vue 使用模板 + 指令(v-if/v-for),关注点分离;React 使用 JSX,在 JS 中写 UI,一切皆 JavaScript。
3. 定位:Vue 是渐进式框架,官方维护全家桶;React 是 UI 库,生态由社区驱动。
4. 组件格式:Vue 是 SFC 单文件组件;React 是函数组件 + Hooks。
2 Vue 的响应式原理是什么?和 React 有什么不同?▶
Vue 3:使用 ES6 Proxy 对对象进行拦截。读取属性时自动收集依赖(track),修改属性时自动触发更新(trigger)。开发者只需修改数据,无需手动触发。
React:使用不可变数据 + setState。调用 setState 后触发整组件 re-render,再通过 Virtual DOM Diff 算出最小 DOM 操作。开发者必须显式调用 setter。
面试加分:Vue 的细粒度更新(组件级 → 模板级)vs React 的组件级更新(需要 memo/useMemo 优化)。
React:使用不可变数据 + setState。调用 setState 后触发整组件 re-render,再通过 Virtual DOM Diff 算出最小 DOM 操作。开发者必须显式调用 setter。
面试加分:Vue 的细粒度更新(组件级 → 模板级)vs React 的组件级更新(需要 memo/useMemo 优化)。
3 为什么选 Vue 不选 React?(或反过来)▶
选 Vue:团队偏 HTML/CSS 背景、需要快速上手、国内项目(Element 生态)、中小型项目、渐进式引入。
选 React:大型团队协作、需要 React Native、追求最大灵活性、已有 React 技术栈、国际化项目。
面试建议:不要拉踩,强调场景适配。两个框架都能做好的产品。
选 React:大型团队协作、需要 React Native、追求最大灵活性、已有 React 技术栈、国际化项目。
面试建议:不要拉踩,强调场景适配。两个框架都能做好的产品。
4 Vue 的 computed 和 React 的 useMemo 有什么区别?▶
功能相同:都是缓存计算结果,依赖不变时不重新计算。
区别:
1. Vue 的
2. Vue 的 computed 有 getter/setter 完整写法;React 的 useMemo 只有 getter。
3. Vue computed 默认就是缓存的;React useMemo 在某些情况下可能被 React 丢弃(React 文档说明不保证缓存)。
区别:
1. Vue 的
computed 自动追踪依赖,无需手动声明;React 的 useMemo 需要手动传入依赖数组。2. Vue 的 computed 有 getter/setter 完整写法;React 的 useMemo 只有 getter。
3. Vue computed 默认就是缓存的;React useMemo 在某些情况下可能被 React 丢弃(React 文档说明不保证缓存)。
5 Vue 的 v-model 和 React 的受控组件有什么区别?▶
Vue v-model:语法糖,自动绑定 value + 监听 input 事件。支持修饰符(.number, .trim, .lazy)。在自定义组件上可实现双向绑定。
React 受控组件:必须手动绑定
核心差异:Vue 的 v-model 是声明式双向绑定;React 强调单向数据流,"双向"通过回调手动实现。
React 受控组件:必须手动绑定
value 和 onChange。每个输入框都需要一个 state + setter,代码更冗长但更可控。核心差异:Vue 的 v-model 是声明式双向绑定;React 强调单向数据流,"双向"通过回调手动实现。
6 Vue 和 React 的 Diff 算法有什么区别?▶
相同点:都使用 Virtual DOM + 同层比较策略,只比较同一层级。
不同点:
1. Vue 的 Diff 能精确知道哪些组件依赖了哪些数据(得益于响应式追踪),可以更精确地触发更新。
2. React 默认从触发 setState 的组件开始整棵子树 re-render,需要手动 memo 优化。
3. Vue 使用最长递增子序列算法优化列表 Diff;React 使用 key 匹配 + 位置移动。
4. Vue 3 引入 Block Tree + PatchFlag 静态标记,进一步优化模板编译产物。
不同点:
1. Vue 的 Diff 能精确知道哪些组件依赖了哪些数据(得益于响应式追踪),可以更精确地触发更新。
2. React 默认从触发 setState 的组件开始整棵子树 re-render,需要手动 memo 优化。
3. Vue 使用最长递增子序列算法优化列表 Diff;React 使用 key 匹配 + 位置移动。
4. Vue 3 引入 Block Tree + PatchFlag 静态标记,进一步优化模板编译产物。
7 Vue 的 Provide/Inject 和 React 的 Context 有什么区别?▶
功能相同:都是实现跨层级组件通信(祖孙传递),避免 props 层层透传。
区别:
1. Vue 使用
2. Vue 的 inject 支持默认值和工厂函数;React 使用 Provider 的 value 或 createContext 的默认值。
3. React Context 变更会导致所有消费者 re-render(除非 memo);Vue 的 provide/inject 也能精确响应式。
区别:
1. Vue 使用
provide(key, value) + inject(key),API 更简洁;React 使用 createContext + Provider 包裹 + useContext。2. Vue 的 inject 支持默认值和工厂函数;React 使用 Provider 的 value 或 createContext 的默认值。
3. React Context 变更会导致所有消费者 re-render(除非 memo);Vue 的 provide/inject 也能精确响应式。
8 Vue 3 Composition API 和 React Hooks 有什么区别?▶
语法相似但底层完全不同:
1. 执行时机:Vue 的 setup() 只执行一次;React 的函数组件每次渲染都会重新执行。
2. 闭包陷阱:React Hooks 有闭包过期问题(stale closure),需要 useCallback/useRef 规避;Vue 的响应式引用始终是最新值。
3. 依赖数组:React useEffect 必须手动声明依赖;Vue watch/watchEffect 自动追踪依赖。
4. 调用顺序:React Hooks 依赖调用顺序(不能用在条件中);Vue 组合式函数无此限制。
5. 心智模型:Vue 是"响应式引用",React 是"快照式状态"。
1. 执行时机:Vue 的 setup() 只执行一次;React 的函数组件每次渲染都会重新执行。
2. 闭包陷阱:React Hooks 有闭包过期问题(stale closure),需要 useCallback/useRef 规避;Vue 的响应式引用始终是最新值。
3. 依赖数组:React useEffect 必须手动声明依赖;Vue watch/watchEffect 自动追踪依赖。
4. 调用顺序:React Hooks 依赖调用顺序(不能用在条件中);Vue 组合式函数无此限制。
5. 心智模型:Vue 是"响应式引用",React 是"快照式状态"。
9 Vue 和 React 在性能优化上的思路有什么不同?▶
Vue(默认优化好):
- Proxy 精确追踪 → 自动细粒度更新
- computed 自动缓存
- 模板编译时静态标记(PatchFlag)
- 开发者较少需要手动优化
React(需手动优化):
- setState → 整组件 re-render → Diff
- React.memo 避免子组件不必要的渲染
- useMemo 缓存计算结果
- useCallback 稳定函数引用
- 虚拟列表(react-window)处理大数据
面试总结:Vue 重编译时优化,React 重运行时优化。
- Proxy 精确追踪 → 自动细粒度更新
- computed 自动缓存
- 模板编译时静态标记(PatchFlag)
- 开发者较少需要手动优化
React(需手动优化):
- setState → 整组件 re-render → Diff
- React.memo 避免子组件不必要的渲染
- useMemo 缓存计算结果
- useCallback 稳定函数引用
- 虚拟列表(react-window)处理大数据
面试总结:Vue 重编译时优化,React 重运行时优化。
10 Vue 和 React 的组件通信方式有哪些?▶
Vue
① Props / Emit
② Provide / Inject
③ Pinia / Vuex
④ EventBus (mitt)
⑤ $refs
① Props / Emit
② Provide / Inject
③ Pinia / Vuex
④ EventBus (mitt)
⑤ $refs
React
① Props / Callback
② Context
③ Redux / Zustand
④ 状态提升
⑤ useRef
① Props / Callback
② Context
③ Redux / Zustand
④ 状态提升
⑤ useRef
面试关键:React 没有 EventBus 概念(不推荐),通常用状态提升或全局状态管理替代。
11 Vue 的 template 和 React 的 JSX 各有什么优缺点?▶
Template(Vue):
+ 声明式,直观易读,设计师友好
+ 编译时优化(静态提升、PatchFlag)
+ 关注点分离(HTML/CSS/JS)
- 灵活性不如 JSX
- 复杂逻辑需要 filters / computed 辅助
JSX(React):
+ 完整的 JS 能力,灵活度高
+ 一个语言搞定 UI 和逻辑
+ TypeScript 类型推导更好
- 学习曲线较陡
- 编译时优化空间有限
+ 声明式,直观易读,设计师友好
+ 编译时优化(静态提升、PatchFlag)
+ 关注点分离(HTML/CSS/JS)
- 灵活性不如 JSX
- 复杂逻辑需要 filters / computed 辅助
JSX(React):
+ 完整的 JS 能力,灵活度高
+ 一个语言搞定 UI 和逻辑
+ TypeScript 类型推导更好
- 学习曲线较陡
- 编译时优化空间有限
12 Vue 的 nextTick 和 React 的 useEffect 执行时机有什么区别?▶
Vue nextTick:在 DOM 更新完成后执行回调。基于微任务(Promise.then)。用于在数据修改后获取更新后的 DOM。
React useEffect:在渲染提交到屏幕之后异步执行。也是微任务,但会批量处理。return 的 cleanup 在下一次 effect 执行前和卸载时执行。
关键差异:nextTick 是一次性的(Promise 风格),useEffect 是声明式的(每次依赖变化都执行)。
React useEffect:在渲染提交到屏幕之后异步执行。也是微任务,但会批量处理。return 的 cleanup 在下一次 effect 执行前和卸载时执行。
关键差异:nextTick 是一次性的(Promise 风格),useEffect 是声明式的(每次依赖变化都执行)。
13 Pinia 和 Redux Toolkit 有什么区别?▶
Pinia(Vue):
- 基于 Composition API,
- 无 mutations,直接修改 state
- 天然 TypeScript 支持
- 支持多个 store,可互相引用
- 极轻量,Vue 官方推荐
Redux Toolkit(React):
- 基于
- 使用 Immer 实现不可变更新
- 单一 store,normalize 数据
- 中间件生态丰富(redux-saga, redux-observable)
- 标准化但学习成本较高
- 基于 Composition API,
defineStore 定义- 无 mutations,直接修改 state
- 天然 TypeScript 支持
- 支持多个 store,可互相引用
- 极轻量,Vue 官方推荐
Redux Toolkit(React):
- 基于
createSlice + reducers- 使用 Immer 实现不可变更新
- 单一 store,normalize 数据
- 中间件生态丰富(redux-saga, redux-observable)
- 标准化但学习成本较高
14 Vue 的 KeepAlive 和 React 的组件缓存有什么区别?▶
Vue KeepAlive:内置组件,使用
React:没有内置的 KeepAlive。常见方案:
1. CSS 隐藏(display:none),组件仍在 DOM 中
2. 使用第三方库 react-activation
3. 状态提升到父组件或全局 store
面试亮点:Vue 的 KeepAlive 是框架级支持,React 需要开发者自行解决或依赖社区方案。
<KeepAlive> 包裹动态组件即可缓存。支持 include/exclude/max 属性精细控制。被缓存的组件触发 activated/deactivated 生命周期。React:没有内置的 KeepAlive。常见方案:
1. CSS 隐藏(display:none),组件仍在 DOM 中
2. 使用第三方库 react-activation
3. 状态提升到父组件或全局 store
面试亮点:Vue 的 KeepAlive 是框架级支持,React 需要开发者自行解决或依赖社区方案。
15 谈谈你对"Vue 重编译时优化,React 重运行时优化"的理解?▶
Vue — 编译时优化:
Vue 的模板编译器在构建阶段就能做大量优化:
1. 静态提升:不变的节点只创建一次
2. PatchFlag:标记动态节点,Diff 时只比较标记部分
3. Block Tree:将模板按结构分块,缩小 Diff 范围
4. 内联事件缓存:避免重复创建事件处理器
React — 运行时优化:
React 的 JSX 无法在编译时做太多假设(JS 的动态性),优化主要在运行时:
1. Fiber 架构:可中断渲染,优先级调度
2. 批量更新:自动合并多次 setState
3. Concurrent Mode:并发渲染,time-slicing
4. 开发者手动优化:memo/useMemo/useCallback
总结:Vue 利用模板的约束性在编译阶段做优化;React 因为 JSX 的灵活性选择在运行时用 Fiber 架构做调度优化。两种策略各有优劣。
Vue 的模板编译器在构建阶段就能做大量优化:
1. 静态提升:不变的节点只创建一次
2. PatchFlag:标记动态节点,Diff 时只比较标记部分
3. Block Tree:将模板按结构分块,缩小 Diff 范围
4. 内联事件缓存:避免重复创建事件处理器
React — 运行时优化:
React 的 JSX 无法在编译时做太多假设(JS 的动态性),优化主要在运行时:
1. Fiber 架构:可中断渲染,优先级调度
2. 批量更新:自动合并多次 setState
3. Concurrent Mode:并发渲染,time-slicing
4. 开发者手动优化:memo/useMemo/useCallback
总结:Vue 利用模板的约束性在编译阶段做优化;React 因为 JSX 的灵活性选择在运行时用 Fiber 架构做调度优化。两种策略各有优劣。
Vue vs React 对照手册 — 面试备战专用 | 最后更新:2026年6月