Vue3 相较于 Vue2 的核心升级是基于 Composition API 重构,同时重写了响应式系统、组件系统等核心模块,引入了大量新 API。
以下按「核心分类+API 详解+使用场景+对比 Vue2」的逻辑,全面梳理 Vue3 新增的关键 API:

一、核心背景:为什么引入新 API?

Vue2 基于「Options API」组织代码(data/methods/computed 等选项),存在两大痛点:

  1. 代码碎片化:关联逻辑(如「获取数据→渲染→监听变化」)分散在不同选项中,大型组件难以维护;
  2. 复用性差:mixins 存在命名冲突、来源不清晰的问题;
  3. TypeScript 支持弱:Options API 天生不贴合 TS 类型推导。

Vue3 的新 API 核心目标是:用 Composition API 聚合逻辑、提升复用性、完善 TS 支持,同时优化响应式、生命周期、组件通信等底层能力。


二、核心新 API 分类详解

(一)Composition API 核心(Vue3 最核心的新特性)

1. setup():组件的「逻辑入口」
  • 作用:替代 Vue2 的 data/methods/computed/watch 等选项,作为 Composition API 的执行上下文,所有组合式 API 都写在这里。
  • 执行时机:组件创建前(beforeCreate 之后、created 之前),此时 this 为 undefined(无组件实例)。
  • 参数:
    • props:组件接收的属性(响应式,不可解构,解构会丢失响应式);
    • context:上下文对象,包含 attrs/slots/emit/expose(替代 Vue2 的 this.$attrs/this.$slots 等)。
  • 返回值:
    • 对象:属性/方法可直接在模板中使用;
    • 函数:自定义渲染函数(替代 render 选项)。
  • 示例:
    <template>
      <div>{{ count }} {{ doubleCount }}</div>
      <button @click="increment">+1</button>
    </template>
    
    <script setup>
    import { ref, computed } from 'vue';
    // 1. 响应式数据
    const count = ref(0);
    // 2. 计算属性
    const doubleCount = computed(() => count.value * 2);
    // 3. 方法
    const increment = () => count.value++;
    </script>
    
  • 对比 Vue2:Vue2 需将 count 放在 data,increment 放在 methods,doubleCount 放在 computed,逻辑分散;Vue3 可按「功能逻辑」聚合。
2. ref():基本类型响应式
  • 作用:为基本类型(字符串/数字/布尔) 创建响应式数据(Vue2 的 data 无法单独为基本类型做响应式),也可包裹对象(内部会调用 reactive)。
  • 核心特点:
    • 底层通过「包裹对象({ value: 原始值 })」实现响应式,访问/修改需通过 .value(模板中自动解包,无需 .value);
    • 支持所有基本类型,解决了 Vue2 响应式对基本类型的「遗漏」。
  • 场景:单个数值、字符串等简单响应式数据(如计数器、输入框值)。
  • 示例:
    const name = ref('Vue3'); // 字符串响应式
    const isShow = ref(true); // 布尔响应式
    console.log(name.value); // 访问:Vue3
    name.value = 'Vue3.4'; // 修改
    
3. reactive():对象/数组响应式
  • 作用:为对象/数组创建「深层响应式」数据,底层基于 ES6 Proxy(而非 Vue2 的 Object.defineProperty)。
  • 核心优势(对比 Vue2):
    • 支持数组响应式(Vue2 的 Object.defineProperty 无法监听数组下标/长度变化);
    • 支持动态添加/删除对象属性(Vue2 需用 Vue.set/Vue.delete);
    • 深层响应式(默认递归所有子属性)。
  • 限制:
    • 仅支持对象/数组,不支持基本类型;
    • 解构会丢失响应式(需用 toRefs 解决)。
  • 示例:
    const user = reactive({ name: '张三', age: 20, hobbies: ['篮球'] });
    user.age = 21; // 响应式修改
    user.hobbies.push('游泳'); // 数组响应式(Vue2 需用 $set)
    user.gender = '男'; // 动态添加属性(Vue2 需用 Vue.set)
    
4. computed():增强型计算属性
  • 作用:创建响应式计算属性,Vue3 增强了「可写性」和「调试能力」。
  • 核心升级:
    • 支持「只读」和「可写」两种模式;
    • 内置缓存,依赖变化才重新计算;
    • 支持 TS 类型推导。
  • 示例:
    // 1. 只读模式(默认)
    const doubleCount = computed(() => count.value * 2);
    // 2. 可写模式
    const fullName = computed({
      get: () => `${firstName.value} ${lastName.value}`,
      set: (val) => {
        const [first, last] = val.split(' ');
        firstName.value = first;
        lastName.value = last;
      }
    });
    fullName.value = '李四 王五'; // 触发setter
    
  • 对比 Vue2:Vue2 的 computed 仅支持函数形式(只读),可写需通过 set 选项,但语法更繁琐;Vue3 语法更简洁,类型支持更好。
5. watch():增强型监听器
  • 作用:监听响应式数据变化,Vue3 大幅增强了灵活性。
  • 核心升级(对比 Vue2):
    • 支持监听单个/多个源(ref/reactive/计算属性/函数返回值);
    • 支持深度监听(无需手动设置 deep: true 也可监听 reactive 深层属性);
    • 支持立即执行(immediate: true)、防抖/节流;
    • 支持停止监听(返回停止函数)。
  • 示例:
    // 1. 监听单个ref
    watch(count, (newVal, oldVal) => {
      console.log(`count从${oldVal}变到${newVal}`);
    }, { immediate: true, deep: false });
    
    // 2. 监听多个源
    watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
      console.log('count或name变化');
    });
    
    // 3. 监听reactive对象的单个属性(需用函数返回)
    watch(() => user.age, (newAge) => {
      console.log('年龄变化:', newAge);
    });
    
    // 4. 停止监听
    const stopWatch = watch(count, () => {});
    stopWatch(); // 手动停止
    
6. watchEffect():自动收集依赖的监听器
  • 作用:「副作用监听器」,立即执行一次,然后自动收集依赖,依赖变化时重新执行(无需指定监听源)。
  • 核心特点:
    • 「隐式监听」:无需手动声明监听谁,代码中用到的响应式数据都会被监听;
    • 「立即执行」:默认 immediate: true,适合「初始化+监听」场景(如请求数据)。
  • 场景:接口请求、DOM 操作等副作用场景(替代 Vue2 的 created + watch)。
  • 示例:
    // 初始化时请求数据,count变化时重新请求
    const stop = watchEffect(() => {
      console.log('请求数据:count=', count.value);
      // fetch(`/api/data?count=${count.value}`).then(res => res.json());
    });
    // 停止监听
    stop();
    
  • 对比 watch:watch 是「显式监听」(指定源),watchEffect 是「隐式监听」(自动收集);watch 可获取新旧值,watchEffect 不能。

(二)响应式系统扩展 API(精细化控制响应式)

Vue3 提供了一系列「细粒度响应式 API」,解决 Vue2 响应式「一刀切」的问题:

API作用场景
readonly()创建「只读响应式」数据(禁止修改,修改会警告)保护全局状态、第三方数据,防止误修改
shallowRef()「浅响应式」ref(仅 .value 本身响应式,深层属性修改不触发更新)大对象/第三方库实例(如 Chart.js),仅需外层响应式
shallowReactive()「浅响应式」reactive(仅外层属性响应式,深层属性非响应式)大型表单对象,避免深层递归影响性能
toRef()将 reactive 对象的单个属性转为 ref(保留响应式)解构 reactive 对象的单个属性,或传递单个属性给子组件
toRefs()将 reactive 对象的所有属性转为 ref(批量)解构 reactive 对象,避免丢失响应式(如 const { name, age } = toRefs(user))
unref()语法糖:isRef(val) ? val.value : val(简化 .value 访问)通用函数中处理 ref/非 ref 数据
isRef()/isReactive()/isReadonly()判断数据类型(ref/reactive/只读)封装通用函数时校验参数类型
triggerRef()手动触发 shallowRef 的更新(修改深层属性后强制更新)修改 shallowRef 的深层属性,触发视图更新

示例(toRefs 解决解构响应式丢失):

const user = reactive({ name: '张三', age: 20 });
// 错误:解构后丢失响应式
const { name, age } = user; 
// 正确:toRefs 转为 ref,保留响应式
const { name, age } = toRefs(user);
name.value = '李四'; // 响应式生效

(三)生命周期钩子(组合式)

Vue3 将 Vue2 的「选项式生命周期」改为「组合式钩子」,全部挂载在 setup 中执行,更贴合逻辑聚合:

Vue2 选项式Vue3 组合式钩子执行时机备注
beforeCreatesetup()(覆盖)组件实例创建前Vue3 无需单独声明
createdsetup()(覆盖)组件实例创建后Vue3 无需单独声明
beforeMountonBeforeMount组件挂载前
mountedonMounted组件挂载后最常用(DOM 操作、请求)
beforeUpdateonBeforeUpdate组件更新前(数据变化后)
updatedonUpdated组件更新后避免在这修改数据(死循环)
beforeDestroyonBeforeUnmount组件卸载前清理定时器/事件监听
destroyedonUnmounted组件卸载后
errorCapturedonErrorCaptured捕获子组件错误
-onRenderTracked调试:响应式依赖被追踪时仅开发环境生效
-onRenderTriggered调试:响应式依赖触发更新时仅开发环境生效

示例:

import { onMounted, onBeforeUnmount } from 'vue';

onMounted(() => {
  console.log('组件挂载完成,可操作DOM');
  // 绑定事件
  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  console.log('组件卸载前,清理资源');
  // 移除事件
  window.removeEventListener('resize', handleResize);
});

(四)组件通信/高级 API

1. defineProps():声明组件属性
  • 作用:替代 Vue2 的 props 选项,在 setup 中声明组件接收的属性,支持 TS 类型校验。
  • 核心优势:无需手动导入(<script setup> 中自动注入),类型推导更友好。
  • 示例:
    <script setup>
    // 方式1:运行时校验
    const props = defineProps({
      title: { type: String, required: true, default: '默认标题' },
      count: { type: Number, default: 0 }
    });
    
    // 方式2:TS 类型校验(推荐)
    const props = defineProps<{
      title: string;
      count?: number;
    }>();
    
    console.log(props.title); // 响应式,不可修改
    </script>
    
2. defineEmits():声明组件事件
  • 作用:替代 Vue2 的 emits 选项,在 setup 中声明组件触发的事件,支持 TS 类型校验。
  • 示例:
    <script setup>
    // 方式1:运行时校验
    const emit = defineEmits(['change', 'update']);
    // 方式2:TS 类型校验
    const emit = defineEmits<{
      (e: 'change', val: string): void;
      (e: 'update', val: number): void;
    }>();
    
    // 触发事件
    emit('change', '新值');
    </script>
    
3. defineExpose():暴露组件属性/方法
  • 作用:替代 Vue2 的 this.$refs 访问子组件属性,Vue3 中 <script setup> 封装的组件默认关闭对外暴露,需手动 defineExpose 暴露。
  • 示例:
    <!-- 子组件 -->
    <script setup>
    const count = ref(0);
    const increment = () => count.value++;
    // 暴露给父组件
    defineExpose({ count, increment });
    </script>
    
    <!-- 父组件 -->
    <template>
      <Child ref="childRef" />
    </template>
    <script setup>
    const childRef = ref(null);
    onMounted(() => {
      console.log(childRef.value.count); // 访问子组件属性
      childRef.value.increment(); // 调用子组件方法
    });
    </script>
    
4. defineOptions()(Vue3.3+)
  • 作用:在 <script setup> 中设置组件选项(如 name/inheritAttrs/components),无需额外写 <script> 标签。
  • 示例:
    <script setup>
    defineOptions({
      name: 'MyComponent', // 组件名(用于递归/调试)
      inheritAttrs: false // 关闭属性继承
    });
    </script>
    
5. provide()/inject():跨层级通信升级
  • 作用:Vue2 已有,但 Vue3 支持响应式传递,且可配合 ref/reactive 实现跨层级数据同步。
  • 示例:
    // 父组件:提供数据
    import { provide, ref } from 'vue';
    const theme = ref('dark');
    provide('theme', theme); // 传递响应式数据
    
    // 子/孙组件:注入数据
    import { inject } from 'vue';
    const theme = inject('theme', ref('light')); // 第二个参数是默认值
    theme.value = 'light'; // 响应式同步到父组件
    

(五)其他核心新 API

1. createApp():创建应用实例
  • 作用:替代 Vue2 的 new Vue(),创建独立的应用实例,隔离不同应用的配置(如全局组件、指令)。
  • 示例:
    // Vue2
    new Vue({ el: '#app', router, store });
    // Vue3
    import { createApp } from 'vue';
    import App from './App.vue';
    const app = createApp(App);
    app.use(router).use(store).mount('#app');
    
  • 优势:多应用实例隔离(如一个页面多个 Vue 应用),避免全局配置污染。
2. Teleport:DOM 传送(组件)
  • 作用:将组件的 DOM 结构传送到指定 DOM 节点(如 body),保留组件逻辑归属,解决弹窗/悬浮窗的样式嵌套问题(之前详细讲过)。
  • 示例:
    <Teleport to="body">
      <div class="modal">弹窗内容</div>
    </Teleport>
    
3. Suspense:异步组件加载
  • 作用:处理异步组件的加载状态(加载中/加载失败),替代手动写 v-if 控制加载状态。
  • 示例:
    <template>
      <Suspense>
        <!-- 异步组件 -->
        <template #default>
          <AsyncComponent />
        </template>
        <!-- 加载中 -->
        <template #fallback>
          <div>加载中...</div>
        </template>
      </Suspense>
    </template>
    
    <script setup>
    // 异步导入组件
    const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'));
    </script>
    
4. useAttrs()/useSlots():获取 attrs/slots
  • 作用:替代 Vue2 的 this.$attrs/this.$slots,在 <script setup> 中获取组件的非 props 属性/插槽。
  • 示例:
    import { useAttrs, useSlots } from 'vue';
    const attrs = useAttrs(); // 获取非props属性(如class、style)
    const slots = useSlots(); // 获取插槽(如默认插槽、具名插槽)
    console.log(attrs.class); // 访问class属性
    console.log(slots.default()); // 渲染默认插槽
    

(六)废弃的 API(对比 Vue2)

Vue3 移除了部分冗余/有缺陷的 API,替代方案如下:

Vue2 废弃 API替代方案
Vue.set/Vue.deletereactive 原生支持动态添加/删除属性
this.$on/$off/$once第三方事件库(如 mitt)
filterscomputed 或自定义函数
$children$refs 或 provide/inject
$scopedSlots合并到 slots,用 useSlots() 获取
new Vue()createApp()

三、核心总结

Vue3 新 API 的设计核心是「灵活性、可组合性、类型友好」:

  1. Composition API(setup/ref/reactive/computed/watch)解决了 Vue2 逻辑碎片化、复用性差的问题;
  2. 细粒度响应式 API(readonly/shallowRef/toRefs 等)让响应式控制更精准;
  3. 组合式生命周期 贴合逻辑聚合,便于维护;
  4. 组件通信 API(defineProps/defineEmits/defineExpose)简化了组件交互,完善了 TS 支持;
  5. createApp/Teleport/Suspense 等扩展了 Vue 的核心能力,适配复杂场景。

对于开发者而言,优先掌握 setup/ref/reactive/computed/watch/onMounted 是基础,再根据场景学习细粒度响应式 API 和高级组件 API,即可覆盖 99% 的开发需求。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐