既然有 react18 怎么能少了 好兄弟 Vue3 Composition API
在 Vue2 的 Options API 时代,我们写组件的方式非常直观:data
管状态,methods
写逻辑,computed
做计算,watch
监听变化。虽然简单易懂,但随着业务复杂度的上升,代码分散、逻辑复用难的问题逐渐暴露。
Vue3 推出的 Composition API 则是一次范式升级,它不仅解决了这些痛点,还为复杂应用的可维护性、类型推导和逻辑复用提供了最佳实践。本文将深入拆解 Composition API 的重要特性,并结合代码案例,让你真正理解它的价值。
一、setup
:逻辑聚合的入口
setup
是 Composition API 的核心入口。它让你在一个函数中声明数据、方法、计算属性和生命周期逻辑,从而实现逻辑内聚。
代码示例:
xml
<script setup>
import { ref, computed } from 'vue'
const count = ref(0)
const double = computed(() => count.value * 2)
function increment() {
count.value++
}
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double: {{ double }}</p>
<button @click="increment">+1</button>
</div>
</template>
传统的 Options API 会把
data
、methods
、computed
分散写,而 Composition API 将相关逻辑集中在一起,更便于维护。
二、ref
和 reactive
:更灵活的数据响应式系统
Vue3 响应式系统基于 Proxy 重写,性能和灵活性大幅提升。
ref
适用于基本类型和单值。reactive
用于对象和数组。
代码示例:
xml
<script setup>
import { ref, reactive } from 'vue'
const name = ref('Alice')
const user = reactive({
age: 18,
hobbies: ['coding', 'reading']
})
function growUp() {
user.age++
}
</script>
<template>
<div>
<p>{{ name }}</p>
<p>{{ user.age }}</p>
<button @click="growUp">长大</button>
</div>
</template>
专家点评 :
Vue3 的
ref
本质是一个带.value
的容器,解耦了响应式与数据本身。而reactive
的 Proxy 机制避免了 Vue2 中Object.defineProperty
的诸多限制,比如新增/删除属性不会丢失响应式。
三、computed
与 watch
:更强大的响应式副作用
computed
用于声明式的派生状态(有缓存)。watch
用于命令式的副作用处理。
代码示例:
xml
<script setup>
import { ref, computed, watch } from 'vue'
const price = ref(100)
const quantity = ref(2)
const total = computed(() => price.value * quantity.value)
watch(total, (newVal, oldVal) => {
console.log(`总价变化: ${oldVal} -> ${newVal}`)
})
</script>
关键差异 :
computed
= 声明式依赖,适合业务派生状态;
watch
= 命令式副作用,适合异步请求、手动逻辑。
四、生命周期钩子函数:语义更清晰
在 Composition API 中,生命周期钩子以 onXxx
的形式存在。
Vue2 | Vue3 (Composition API) |
---|---|
created | setup() |
mounted | onMounted |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
代码示例:
xml
<script setup>
import { onMounted, onUnmounted } from 'vue'
onMounted(() => {
console.log('组件挂载完成')
})
onUnmounted(() => {
console.log('组件已销毁')
})
</script>
这种显式的
onMounted
、onUnmounted
调用方式,不仅语义清晰,还能让 IDE 类型推导更强大。
五、逻辑复用利器:自定义 Hook(Composable)
最大的亮点就是 逻辑复用 。在 Vue2 里复用逻辑通常用 mixin,但存在命名冲突和来源不明的问题。Vue3 的解决方案是 Composable ------ 一个返回响应式状态的函数。
代码示例:
javascript
// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
xml
<script setup>
import { useMouse } from './useMouse'
const { x, y } = useMouse()
</script>
<template>
<p>Mouse: {{ x }}, {{ y }}</p>
</template>
专家点评 :
Composable 是 Vue3 的"函数式逻辑复用"方案,天然避免了 mixin 的隐式依赖问题,类似 React 的 Hook,但保留了 Vue 响应式的直观性。
六、provide
/ inject
:依赖注入更优雅
在复杂组件树中,props
层层传递会非常繁琐。Vue3 的 provide/inject
提供了 跨层级状态共享 的简洁方案。
代码示例:
xml
<!-- Parent.vue -->
<script setup>
import { provide, ref } from 'vue'
const theme = ref('dark')
provide('theme', theme)
</script>
<template>
<slot />
</template>
xml
<!-- Child.vue -->
<script setup>
import { inject } from 'vue'
const theme = inject('theme', 'light') // 默认值 light
</script>
<template>
<p>Theme: {{ theme }}</p>
</template>
七、TypeScript 友好度大幅提升
Vue3 从设计之初就考虑了 类型推导,结合 Composition API,几乎可以做到完整的 IDE 提示。
代码示例:
xml
<script setup lang="ts">
import { ref } from 'vue'
const count = ref<number>(0)
function add(delta: number): void {
count.value += delta
}
</script>
相比 Vue2 依赖第三方装饰器方案,Vue3 的 TS 支持是原生的,更稳定、更高效。
八、总结:为什么 Composition API 是前端的"终极武器"?
- ✅ 逻辑聚合:相关代码不再分散。
- ✅ 响应式增强:基于 Proxy,性能更强。
- ✅ 逻辑复用:Composable 函数彻底解决 mixin 痛点。
- ✅ TS 友好:原生支持类型推导。
- ✅ 更灵活的生命周期:语义清晰、可组合。
一句话总结:Composition API 让 Vue 从"易用"走向了"工程化",这也是 Vue3 能在大型项目中稳健落地的关键原因。