Vue3组合式API完全指南

发布于2026-03-26 19:44 阅读11次 Vue 3带来的组合式API彻底改变了Vue应用的开发方式。深入讲解setup语法糖、ref、reactive、computed、watch等核心API,帮助开发者快速掌握Vue 3的现代化开发模式。
在Vue 2中,我们使用选项式API(Options API)来定义组件。这种方式将数据、方法、计算属性、生命周期钩子分散在不同的选项中,对于小型组件来说,这种组织方式清晰直观。然而,随着组件变得越来越复杂,问题也随之而来。想象一下,当一个组件有几百行代码时,与同一个功能相关的逻辑被分散在data、methods、computed、watch等多个地方,维护和理解代码变得困难重重。组合式API的出现就是为了解决这个痛点。它允许我们将与同一个功能相关的代码组织在一起,而不是按照选项类型分散开来。举个例子,假设我们有一个搜索功能,在Vue 2中,搜索相关的逻辑可能分布在data的搜索关键词、methods的处理函数、computed的过滤结果、watch的监听器等地方。而在Vue 3中,我们可以将所有这些逻辑放在一个useSearch函数中,形成一个独立的功能模块。这种变化带来的好处是显而易见的:代码更容易阅读和理解,功能模块更容易复用,类型推断更加完善。 # setup函数:组合式API的入口
setup函数是组合式API的入口,它是组件的一个新的配置项,在组件创建之前执行,this不会指向组件实例。setup函数接收两个参数:props和context。props是响应式的,可以用来接收父组件传递的数据;context是一个对象,包含attrs、emit、slots等属性。```vue
<script setup> import { ref } from 'vue' // 定义响应式数据 const count = ref(0) // 定义函数 const increment = () => { count.value++ } // 返回供模板使用的变量和方法 return { count, increment } </script> <template> <button @click="increment">{{ count }}</button> </template>```值得注意的是,使用script setup语法糖时,代码实际上会在setup函数中执行,而且所有在setup中定义的变量和方法都自动暴露给模板,无需手动return。这大大简化了代码编写。 # ref和reactive:响应式数据的基石
Vue 3提供了两种方式来创建响应式数据:ref和reactive。它们各有特点,适用于不同的场景。## ref:基础类型的响应式包装ref用于创建基础类型(字符串、数字、布尔值等)的响应式数据。它返回一个包含value属性的对象,当value发生变化时,Vue会自动更新视图。```javascript import { ref } from 'vue' const count = ref(0) const message = ref('Hello') // 访问和修改需要使用。value console.log(count.value) // 0 count.value++ ```在模板中使用时,Vue会自动解包,不需要写。value。## reactive:对象的响应式包装reactive用于创建对象的响应式数据,它不需要。value,直接操作对象的属性即可。```javascript import { reactive } from 'vue' const state = reactive({ count: 0, name: 'Vue', user: { age: 18 } }) // 直接访问和修改 state.count++ state.user.age = 20 ```选择建议:基础类型用ref,对象类型用reactive。ref也可以包装对象,但reactive更加直观。需要注意的是,reactive返回的是原始对象的Proxy,任何替换整个对象的操作都会丢失响应性,这时应该使用ref。 # computed:智能的计算属性
计算属性computed用于创建基于现有响应式数据的派生数据。它会自动追踪依赖,并在依赖变化时重新计算。与methods相比,computed具有缓存特性,只有当依赖发生变化时才会重新计算。```javascript import { ref, computed } from 'vue' const firstName = ref('John') const lastName = ref('Doe') // 创建计算属性 const fullName = computed(() => { return firstName.value + ' ' + lastName.value }) ```computed可以接受一个对象参数,用于配置getter和setter:```javascript const count = ref(0) const double = computed({ get: () => count.value * 2, set: (val) => { count.value = val / 2 } }) ``` # watch和watchEffect:数据变化的监听器
watch和watchEffect都用于监听响应式数据的变化,但使用场景和特性有所不同。## watch:精确监听特定数据watch需要明确指定监听的数据源,并支持更复杂的配置选项。```javascript import { ref, watch } from 'vue' const count = ref(0) // 监听单个ref watch(count, (newVal, oldVal) => { console.log(`count从${oldVal}变为${newVal}`) }) // 监听多个数据 watch( [count, () => someOtherRef.value], ([newCount, newOther], [oldCount, oldOther]) => { console.log('数据变化了') } ) ```watch还有immediate、deep、flush等配置选项,可以满足各种需求。## watchEffect:自动追踪依赖watchEffect会自动追踪其回调函数中使用的所有响应式数据,简洁直观。```javascript import { ref, watchEffect } from 'vue' const count = ref(0) const double = ref(0) watchEffect(() => { double.value = count.value * 2 console.log('count变化了') }) ```watchEffect适合简单场景,watch适合需要精确控制的复杂场景。 # 生命周期钩子的组合式写法
在setup函数中,我们可以使用onMounted、onUpdated、onUnmounted等函数来注册生命周期钩子。这些函数与选项式API中的生命周期钩子对应,但可以多次调用。```javascript import { onMounted, onUpdated, onUnmounted } from 'vue' onMounted(() => { console.log('组件挂载完成') }) onUpdated(() => { console.log('组件更新完成') }) onUnmounted(() => { console.log('组件卸载') }) ```setup函数本身在beforeCreate之后、created之前执行,相当于Vue 2中的beforeCreate和created钩子。常用的生命周期钩子映射如下:- beforeCreate → setup()- created → setup()- beforeMount → onBeforeMount- mounted → onMounted- beforeUpdate → onBeforeUpdate- updated → onUpdated- beforeUnmount → onBeforeUnmount- unmounted → onUnmounted # 自定义组合式函数:逻辑复用的利器
组合式API最强大的特性之一就是可以轻松创建可复用的逻辑模块。我们可以将相关的响应式数据、计算属性、方法等封装成一个自定义函数,这种函数被称为组合式函数(Composables)。```javascript // useMouse.js import { ref, onMounted, onUnmounted } from 'vue' export function useMouse() { const x = ref(0) const y = ref(0) function update(event) { x.value = event.pageX y.value = event.pageY } onMounted(() => window.addEventListener('mousemove', update)) onUnmounted(() => window.removeEventListener('mousemove', update)) return { x, y } } ```在组件中使用:```vue <script setup> import { useMouse } from './useMouse' const { x, y } = useMouse() </script> <template> 鼠标位置: {{ x }}, {{ y }} </template> ```这种模式让逻辑复用变得极其简单,而且是真正的响应式复用,不是mixin那种隐式依赖的写法。Vue社区已经涌现出大量优秀的组合式函数库,如VueUse,提供了包括useClipboard、useStorage、useGeolocation等实用的工具函数。 # 异步数据处理:Suspense与Error Boundaries
Vue 3引入了Suspense组件,用于处理异步组件的加载状态。它允许我们在异步组件加载时展示fallback内容。```vue <template> <Suspense> <template #default> <AsyncComponent /> </template> <template #fallback> 加载中... </template> </Suspense> </template> ```Suspense特别适合配合异步setup函数使用,在setup中可以进行异步操作,如获取数据、加载配置等。配合错误边界Error Boundaries,可以优雅地处理加载失败的情况。 # 总结
Vue 3的组合式API为前端开发带来了全新的范式。它让代码组织更加清晰,逻辑复用更加简单,类型推断更加完善。虽然组合式API学习曲线比选项式API稍陡,但一旦掌握,你会发现它带来的好处是巨大的。在实际项目中,我们可以根据场景灵活选择:小型简单组件可以使用选项式API,保持代码的简洁直观;大型复杂组件则适合使用组合式API,更好地组织和管理代码。Vue 3完全兼容选项式API,两种方式可以共存,这体现了Vue渐进式框架的设计理念。希望这篇文章能帮助你快速掌握Vue 3的组合式API,在实际项目中发挥它的威力。记住,熟能生巧,多动手实践是掌握任何技术的最佳途径。