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 之前),此时 thisundefined(无组件实例)。
  • 参数
    • 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 放在 dataincrement 放在 methodsdoubleCount 放在 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();
    
  • 对比 watchwatch 是「显式监听」(指定源),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 组合式钩子 执行时机 备注
beforeCreate setup()(覆盖) 组件实例创建前 Vue3 无需单独声明
created setup()(覆盖) 组件实例创建后 Vue3 无需单独声明
beforeMount onBeforeMount 组件挂载前
mounted onMounted 组件挂载后 最常用(DOM 操作、请求)
beforeUpdate onBeforeUpdate 组件更新前(数据变化后)
updated onUpdated 组件更新后 避免在这修改数据(死循环)
beforeDestroy onBeforeUnmount 组件卸载前 清理定时器/事件监听
destroyed onUnmounted 组件卸载后
errorCaptured onErrorCaptured 捕获子组件错误
- 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.delete reactive 原生支持动态添加/删除属性
this.$on/$off/$once 第三方事件库(如 mitt)
filters computed 或自定义函数
$children $refsprovide/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 垂直技术社区,欢迎活跃、内容共建。

更多推荐