React 开发者学 Vue3:Composition API 核心用法对照与避坑实录

张开发
2026/4/21 22:02:01 15 分钟阅读

分享文章

React 开发者学 Vue3:Composition API 核心用法对照与避坑实录
一、前言Vue3 Composition API 是 Vue 开发的新范式如果你是 React 开发者Vue3 的 Composition API 会让你感到既熟悉又陌生。本文从 React 开发者视角逐一对照 Hooks 与 Composition API 的核心用法帮你快速上手并避开常见坑。二、核心概念对照2.1 状态管理useState vs ref/reactive// React const [count, setCount] useState(0); const [user, setUser] useState({ name: , age: 0 }); setCount(prev prev 1); setUser(prev ({ ...prev, name: Tom }));// Vue3 const count ref(0); const user reactive({ name: , age: 0 }); count.value; user.name Tom; // 直接赋值不需要 setState关键差异Vue3 的reactive对象可以直接修改属性无需 immer 或 spread 语法。ref基础类型需要.value在模板中自动解包。2.2 副作用useEffect vs watchEffect/watch// React useEffect(() { document.title ${count} times clicked; return () { // 清理副作用 }; }, [count]);// Vue3 watchEffect(() { document.title ${count.value} times clicked; // 返回清理函数 return () { /* cleanup */ }; }); // 精确监听 watch(count, (newVal, oldVal) { console.log(${oldVal} → ${newVal}); });关键差异Vue3 的watchEffect自动追踪依赖不需要手写依赖数组。watch精确监听类似 useEffect 指定 deps。2.3 计算属性useMemo vs computed// React const doubleCount useMemo(() count * 2, [count]);// Vue3 const doubleCount computed(() count.value * 2); // doubleCount.value 是只读的依赖变化时自动更新关键差异Vue3 的computed天然缓存不需要手动写 deps访问.value即得最新值。三、生命周期对照React HookVue3 Composition时机无构造函数setup()本身组件初始化useEffect(fn, [])onMounted(fn)DOM 挂载后useEffect(() fn, [])onUnmounted(fn)组件卸载useEffect(fn, [dep])watch/watchEffect依赖变化无onUpdated(fn)每次更新后// Vue3 生命周期示例 import { onMounted, onUnmounted, onUpdated } from vue; export function useEventListener(event: string, handler: Function) { onMounted(() window.addEventListener(event, handler as EventListener)); onUnmounted(() window.removeEventListener(event, handler as EventListener)); }四、组合式函数类比 React 自定义 Hooks// React 自定义 Hook function useWindowSize() { const [size, setSize] useState({ width: 0, height: 0 }); useEffect(() { const handler () setSize({ width: window.innerWidth, height: window.innerHeight }); window.addEventListener(resize, handler); handler(); return () window.removeEventListener(resize, handler); }, []); return size; }// Vue3 组合式函数Composable export function useWindowSize() { const width ref(window.innerWidth); const height ref(window.innerHeight); const handler () { width.value window.innerWidth; height.value window.innerHeight; }; onMounted(() window.addEventListener(resize, handler)); onUnmounted(() window.removeEventListener(resize, handler)); return { width, height }; } // 使用 const { width, height } useWindowSize();五、常见坑点坑1解构 reactive 对象失去响应性// ❌ 错误解构后 name 不再是响应式的 const { name } reactive({ name: Tom }); // ✅ 正确用 toRefs 保持响应性 const state reactive({ name: Tom, age: 18 }); const { name, age } toRefs(state);坑2ref 在模板里不需要 .value但在 JS 里需要const count ref(0); // 模板中{{ count }} ← 自动解包不用 .value // JS中count.value ← 必须 .value坑3watch 默认不立即执行// React useEffect 会在 mount 时立即执行 useEffect(() { fetchData(); }, [userId]); // Vue3 watch 默认不立即执行需要加 immediate: true watch(userId, fetchData, { immediate: true }); // 或者用 watchEffect总是立即执行 watchEffect(() fetchData(userId.value));六、总结从 React 迁移的心智模型ref/reactive 替代 useStatereactive 对象可以直接修改无需 setStatewatchEffect/watch 替代 useEffect自动追踪依赖无需 deps 数组computed 替代 useMemo天然缓存语法更简洁Composables 替代自定义 Hooks结构和写法几乎一致最大不同Vue3 用 Proxy 追踪依赖响应式是自动的React 需要手动声明 deps关注我React↔Vue3 迁移避坑系列持续更新帮你平滑过渡觉得有用点赞收藏关注后续持续更新《框架迁移避坑》系列React↔Vue3↔Angular 全覆盖。标签react | vue3 | compositionapi | 前端 | 对比 | 避坑

更多文章