vue3 组合式 API 详解
✅ 一、什么是组合式 API(Composition API)?
Composition API 是 Vue 3 引入的一套新的组件编写方式。
它的核心思想是:
按“逻辑”组织代码,而不是按“选项(data / methods / computed ...)”组织代码。
传统 Options API 的代码是分散的,而 Composition API 把相关逻辑集中写在一起,更利于可维护、可拆分、可复用。
✅ 二、为什么要使用 Composition API?
1. 逻辑集中,不再分散在各个选项里
例如一个功能需要 data、methods、watch、computed
在 Options API 中会分散在不同的块:
data()
computed
methods
watch
而 Composition API 中可以集中放在 setup() 中。
2. 更强的逻辑复用(不再被 mixins 限制)
使用**组合函数(Composables)**可以像 React Hooks 一样复用逻辑。
3. 更适合 TypeScript
Composition API 更符合 TS 类型推断。
4. 更利于代码压缩与 tree-shaking
未使用的函数不会被打包。
✅ 三、Composition API 核心功能总览
| 功能 | 作用 |
|---|---|
| setup() | 组合式 API 的入口 |
| ref() | 定义基本类型响应式数据 |
| reactive() | 定义对象响应式数据 |
| computed() | 定义计算属性 |
| watch() | 侦听数据变化 |
| watchEffect() | 自动依赖追踪的侦听器 |
| 生命周期钩子 | 如 onMounted/onUnmounted |
| provide/inject | 组件通信(依赖注入) |
| defineProps / defineEmits | 单文件组件 SFC 中使用 |
✅ 四、Composition API 最重要的:setup()
Vue 3 组件使用 Composition API 时,逻辑基本写在 setup() 中:
<script setup>
import { ref, reactive, computed, watch, onMounted } from 'vue'const count = ref(0)function increment() {count.value++
}onMounted(() => {console.log('组件已挂载')
})
</script><template><button @click="increment">{{ count }}</button>
</template>
setup() 的特点
在组件创建之前执行
不能访问 this(与 Options API 完全不同)
返回的变量和方法才能在模板中使用
✅ 五、ref() —— 定义基本类型响应式数据
const count = ref(0)ref 定义的变量需要通过 .value 访问:
count.value++
console.log(count.value)
✅ 六、reactive() —— 定义对象响应式数据
const state = reactive({name: 'Tom',age: 18
})
reactive 定义的对象不需要 .value:
state.age++
注意:reactive 只能用于对象
对基本类型无效(要用 ref)
ref vs reactive 对比
| ref | reactive |
|---|---|
| 可用于基本类型 | 只能用于对象 |
必须用 .value | 不需要 .value |
| 可以包装对象,但会变成嵌套 | 直接生成 Proxy 对象 |
✅ 七、computed() —— 定义计算属性
const firstName = ref('Tom')
const lastName = ref('Jerry')const fullName = computed(() => {return firstName.value + ' ' + lastName.value
})
支持 getter / setter:
const fullName = computed({get() {return firstName.value + ' ' + lastName.value},set(value) {const parts = value.split(' ')firstName.value = parts[0]lastName.value = parts[1]}
})
✅ 八、watch 和 watchEffect
watch:指定侦听目标
watch(count, (newVal, oldVal) => {console.log('变化:', newVal)
})
侦听多个:
watch([count, firstName], ([newCount, newName]) => {console.log(newCount, newName)
})
watchEffect:自动依赖收集
不需要指定侦听目标:
watchEffect(() => {console.log('count is:', count.value)
})
适合副作用操作。
✅ 九、生命周期函数(组合式写法)
组合式 API 的生命周期函数全部以 onXxx 命名。
| Options API | Composition API |
|---|---|
| created | 无(使用 setup 代替) |
| mounted | onMounted |
| updated | onUpdated |
| unmounted | onUnmounted |
| beforeMount | onBeforeMount |
| beforeUpdate | onBeforeUpdate |
| beforeUnmount | onBeforeUnmount |
示例:
onMounted(() => {console.log('组件挂载了')
})
✅ 十、组件通信:props / emits
1. <script setup> 中使用 defineProps
<script setup>
const props = defineProps({title: String,age: Number
})
</script>
2. Emits
<script setup>
const emit = defineEmits(['update'])function sendData() {emit('update', 123)
}
</script>
✅ 十一、组合逻辑复用:自定义组合函数(Composables)
可把可复用的逻辑抽成“函数”,像 React Hooks 一样。
示例:封装一个计数器逻辑
文件:useCounter.js
import { ref } from 'vue'export function useCounter() {const count = ref(0)const inc = () => count.value++const dec = () => count.value--return { count, inc, dec }
}
使用:
<script setup>
import { useCounter } from './useCounter'const { count, inc, dec } = useCounter()
</script><template><button @click="dec">-</button>{{ count }}<button @click="inc">+</button>
</template>
✅ 十二、Composition API 与 Options API 对比总结
| 对比项 | Options API | Composition API |
|---|---|---|
| 代码结构 | 按 data/methods/watch 分散 | 逻辑集中,清晰 |
| 逻辑复用 | mixins 有命名冲突 | composables 优秀 |
| TypeScript 支持 | 较差 | 非常友好 |
| 可维护性 | 大型项目易混乱 | 更清晰结构化 |
| 新手学习成本 | 低 | 略高 |
🔥 十三、完整示例:计数器 + 计算属性 + watch
<script setup>
import { ref, computed, watch, onMounted } from 'vue'const count = ref(0)const double = computed(() => count.value * 2)watch(count, (n, o) => {console.log(`count: ${o} -> ${n}`)
})function inc() {count.value++
}onMounted(() => {console.log('组件挂载')
})
</script><template><h1>Count: {{ count }}</h1><h2>Double: {{ double }}</h2><button @click="inc">增加</button>
</template>
