Vue3 组合式 API(Composition API)最全入门指南
本文将从诞生背景、核心语法、setup 函数、响应式 API、生命周期、逻辑复用等维度带你从零到一掌握 Vue3 组合式 API告别选项式 API 的代码碎片化问题。一、为什么需要组合式 API在 Vue2 中我们使用**选项式 APIOptions API**组织代码代码按data/methods/computed/watch等选项分类小型项目结构清晰但中大型项目会出现逻辑碎片化同一个功能的代码分散在多个选项中阅读和复用都很困难// Vue2 选项式 API 示例计数器逻辑exportdefault{data(){return{count:0,doubleCount:0}},methods:{increment(){this.count},decrement(){this.count--}},computed:{double(){returnthis.count*2}},watch:{count(newVal){console.log(count 变为,newVal)}},mounted(){console.log(组件已挂载初始 count,this.count)}}组合式 API 的核心优势按功能逻辑组织代码而非选项类型逻辑聚合便于阅读、维护和复用原生支持 TypeScript类型推导更友好更灵活的逻辑拆分与组合适合大型项目二、组合式 API 核心入口setup 函数setup是组合式 API 的入口函数所有组合式逻辑都在setup中定义。2.1 setup 函数的基本用法template div p{{ count }}/p button clickincrement1/button /div /template script import { ref } from vue export default { // setup 函数接收 props 和 context 两个参数 setup(props, context) { // 1. 定义响应式数据 const count ref(0) // 2. 定义方法 const increment () { count.value } // 3. 返回需要在模板中使用的数据和方法 return { count, increment } } } /script2.2 setup 函数的参数props组件接收的 props是响应式的不能直接解构会丢失响应式context包含attrs/slots/emit三个属性等价于 Vue2 中的$attrs/$slots/$emitsetup(props,context){// 正确保持响应式访问 propsconsole.log(props.title)// 错误解构会丢失响应式// const { title } props// context 用法const{attrs,slots,emit}contextemit(update:title,新标题)}2.3script setup语法糖推荐为了简化setup写法Vue3 提供了script setup语法糖无需手动return顶层声明的变量/函数自动暴露给模板自动导入组件无需手动注册更简洁的 TypeScript 支持template div p{{ count }}/p button clickincrement1/button /div /template !-- 使用 script setup 语法糖 -- script setup import { ref } from vue // 直接定义响应式数据 const count ref(0) // 直接定义方法 const increment () { count.value } /script三、核心响应式 APIref / reactive / computed / watch组合式 API 提供了一套全新的响应式 API用于管理状态。3.1 ref基础响应式变量ref用于包装基本类型字符串/数字/布尔等和复杂类型在setup/script setup中需要通过.value访问模板中会自动解包。script setup import { ref } from vue // 基本类型 const count ref(0) const message ref(Hello Vue3) // 复杂类型 const user ref({ name: Tom, age: 25 }) // 修改值需要 .value count.value user.value.age 26 /script template !-- 模板中自动解包无需 .value -- p{{ count }}/p p{{ message }}/p p{{ user.name }} - {{ user.age }}/p /template3.2 reactive对象/数组响应式reactive用于创建对象/数组的响应式代理不能直接解构会丢失响应式如需解构请使用toRefs。script setup import { reactive, toRefs } from vue const user reactive({ name: Tom, age: 25, hobbies: [coding, reading] }) // 错误解构会丢失响应式 // const { name, age } user // 正确使用 toRefs 保持响应式 const { name, age } toRefs(user) // 修改响应式对象 user.age user.hobbies.push(gaming) /script3.3 computed计算属性computed用于创建只读/可写的计算属性依赖变化时自动更新。script setup import { ref, computed } from vue const count ref(0) // 只读计算属性 const doubleCount computed(() count.value * 2) // 可写计算属性 const writableDouble computed({ get() { return count.value * 2 }, set(val) { count.value val / 2 } }) /script template p{{ doubleCount }}/p button clickwritableDouble 10设置为 10/button /template3.4 watch侦听器watch用于侦听响应式数据变化支持侦听单个/多个数据源配置深度监听、立即执行等。script setup import { ref, reactive, watch } from vue const count ref(0) const user reactive({ name: Tom, age: 25 }) // 侦听单个 ref watch(count, (newVal, oldVal) { console.log(count 变化, oldVal, →, newVal) }) // 侦听 reactive 对象的某个属性需用 getter 函数 watch(() user.age, (newVal) { console.log(age 变为, newVal) }) // 侦听多个数据源 watch([count, () user.name], ([newCount, newName]) { console.log(count 或 name 变化) }) // 深度侦听 立即执行 watch( () user.hobbies, (newVal) console.log(hobbies 变化), { deep: true, immediate: true } ) /script四、组合式 API 中的生命周期Vue3 中生命周期函数以组合式函数的形式提供需要手动导入并在setup中调用。Vue2 选项式 APIVue3 组合式 API说明beforeCreate合并到setup无需单独声明created合并到setup无需单独声明beforeMountonBeforeMount组件挂载前mountedonMounted组件挂载后beforeUpdateonBeforeUpdate组件更新前updatedonUpdated组件更新后beforeDestroyonBeforeUnmount组件卸载前destroyedonUnmounted组件卸载后script setup import { onMounted, onUnmounted, ref } from vue const timer ref(null) onMounted(() { console.log(组件已挂载) timer.value setInterval(() { console.log(定时器运行中) }, 1000) }) onUnmounted(() { console.log(组件即将卸载) clearInterval(timer.value) // 清理定时器 }) /script五、逻辑复用自定义 Composables组合式 API 最大的优势之一是逻辑复用我们可以将可复用的逻辑封装为自定义 Composables函数。5.1 封装一个计数器 Composable// composables/useCounter.jsimport{ref,computed}fromvueexportfunctionuseCounter(initialValue0){constcountref(initialValue)constincrement()count.valueconstdecrement()count.value--constreset()count.valueinitialValueconstdoublecomputed(()count.value*2)// 返回需要暴露的状态和方法return{count,increment,decrement,reset,double}}5.2 在组件中使用 Composabletemplate div p{{ count }} - 双倍{{ double }}/p button clickincrement1/button button clickdecrement-1/button button clickreset重置/button /div /template script setup // 导入自定义 Composable import { useCounter } from ./composables/useCounter.js // 直接使用逻辑完全复用 const { count, increment, decrement, reset, double } useCounter(0) /script5.3 封装一个鼠标位置追踪 Composable// composables/useMouse.jsimport{ref,onMounted,onUnmounted}fromvueexportfunctionuseMouse(){constxref(0)constyref(0)constupdate(e){x.valuee.clientX y.valuee.clientY}onMounted(()window.addEventListener(mousemove,update))onUnmounted(()window.removeEventListener(mousemove,update))return{x,y}}template p鼠标位置{{ x }}, {{ y }}/p /template script setup import { useMouse } from ./composables/useMouse.js const { x, y } useMouse() /script六、组合式 API 与选项式 API 对比维度选项式 API组合式 API代码组织按选项类型data/methods 等按功能逻辑逻辑复用依赖 mixins易冲突自定义 Composables无冲突TypeScript 支持弱需额外装饰器原生友好类型推导完善适用场景小型项目、快速原型中大型项目、复杂逻辑学习曲线平缓易上手稍陡但长期维护成本更低七、常见问题与避坑指南ref 必须用 .value 访问在setup/script setup中修改 ref 必须加.value模板中自动解包无需.valuereactive 不能直接解构直接解构会丢失响应式需用toRefs转换watch 侦听 reactive 属性需用 getter直接侦听user.age不会生效需写成() user.age生命周期函数必须在 setup 顶层调用不能在条件/循环中调用Composables 必须以 use 开头这是 Vue3 社区约定便于识别和工具支持八、总结组合式 API 是 Vue3 最核心的变革之一它解决了选项式 API 在大型项目中的逻辑碎片化问题提供了更灵活的逻辑复用方式自定义 Composables原生支持 TypeScript让大型项目更易维护配合script setup语法糖开发体验大幅提升如果你还在使用选项式 API不妨从简单的组件开始尝试组合式 API逐步感受它带来的开发效率提升。