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


一、前言:Vue3 Composition API 是 Vue 开发的新范式

如果你是 React 开发者,Vue3 的 Composition API 会让你感到既熟悉又陌生。本文从 React 开发者视角,逐一对照 Hooks 与 Composition API 的核心用法,帮你快速上手并避开常见坑。


二、核心概念对照

2.1 状态管理:useState vs ref/reactive

tsx 复制代码
// React
const [count, setCount] = useState(0);
const [user, setUser] = useState({ name: '', age: 0 });
setCount(prev => prev + 1);
setUser(prev => ({ ...prev, name: 'Tom' }));
ts 复制代码
// 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

tsx 复制代码
// React
useEffect(() => {
  document.title = `${count} times clicked`;
  return () => {
    // 清理副作用
  };
}, [count]);
ts 复制代码
// 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

tsx 复制代码
// React
const doubleCount = useMemo(() => count * 2, [count]);
ts 复制代码
// Vue3
const doubleCount = computed(() => count.value * 2);
// doubleCount.value 是只读的,依赖变化时自动更新

关键差异 :Vue3 的 computed 天然缓存,不需要手动写 deps,访问 .value 即得最新值。


三、生命周期对照

React Hook Vue3 Composition 时机
无(构造函数) setup() 本身 组件初始化
useEffect(fn, []) onMounted(fn) DOM 挂载后
useEffect(() => fn, []) onUnmounted(fn) 组件卸载
useEffect(fn, [dep]) watch/watchEffect 依赖变化
无 onUpdated(fn) 每次更新后
ts 复制代码
// 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)

tsx 复制代码
// 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;
}
ts 复制代码
// 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 对象失去响应性

ts 复制代码
// ❌ 错误:解构后 name 不再是响应式的
const { name } = reactive({ name: 'Tom' });

// ✅ 正确:用 toRefs 保持响应性
const state = reactive({ name: 'Tom', age: 18 });
const { name, age } = toRefs(state);

坑2:ref 在模板里不需要 .value,但在 JS 里需要

ts 复制代码
const count = ref(0);
// 模板中:{{ count }}  ← 自动解包,不用 .value
// JS中:count.value++  ← 必须 .value

坑3:watch 默认不立即执行

ts 复制代码
// React useEffect 会在 mount 时立即执行
useEffect(() => { fetchData(); }, [userId]);

// Vue3 watch 默认不立即执行,需要加 immediate: true
watch(userId, fetchData, { immediate: true });
// 或者用 watchEffect(总是立即执行)
watchEffect(() => fetchData(userId.value));

六、总结:从 React 迁移的心智模型

  1. ref/reactive 替代 useState,reactive 对象可以直接修改,无需 setState
  2. watchEffect/watch 替代 useEffect,自动追踪依赖,无需 deps 数组
  3. computed 替代 useMemo,天然缓存,语法更简洁
  4. Composables 替代自定义 Hooks,结构和写法几乎一致
  5. 最大不同:Vue3 用 Proxy 追踪依赖,响应式是自动的;React 需要手动声明 deps

💬 关注我,React↔Vue3 迁移避坑系列持续更新,帮你平滑过渡!


💬 觉得有用?点赞+收藏+关注! 后续持续更新《框架迁移避坑》系列,React↔Vue3↔Angular 全覆盖。

标签:react | vue3 | compositionapi | 前端 | 对比 | 避坑

相关推荐
斯内普吖7 小时前
(开源)宠物饲养系统实战指南 基于 Java + SSM + Vue + MySQL
java·vue.js·mysql·开源·宠物
可乐鸡翅yeah_7 小时前
新手梳理:HLS 线上问题,哪些该提给 CDN,哪些该找后端切片服务
开发语言·前端·javascript·vue.js·网络协议·http·m3u8在线
Q26433650238 小时前
【有源码】基于SpringBoot+Vue的博物馆展览与服务一体化平台-java博物馆数字化展品展示与交互平台设计
java·vue.js·spring boot·spring·毕业设计·javaweb·课程设计
এ慕ོ冬℘゜8 小时前
es6基础
前端·javascript·es6
ym hyd 1118 小时前
汽车零部件缺陷管理系统源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·汽车·毕设
可乐鸡翅yeah_9 小时前
hls.js 缓冲区参数 maxBufferLength、maxBufferSize 通俗讲解与业务调参
开发语言·javascript·ios·音视频·safari·m3u8
paopaokaka_luck9 小时前
高校社团管理(AI辅助任务分配、协同过滤算法推荐、ECharts数据可视化、活动参与闭环、校园交流与反馈、器材借还管理)
java·前端·javascript·spring boot·数据分析·echarts
vx_Biye_Design9 小时前
springboot小区管理系统68491-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express
5008410 小时前
React Native for OpenHarmony 实战:三方库 react-native-volume-control 的鸿蒙化适配指南
javascript·react native·react.js·electron·harmonyos
薛一半10 小时前
React-Redux三重优化实战揭秘
javascript·vue.js·react.js