Vue 3 组合式函数实战指南
深入探讨Vue3组合式函数的设计原则与实战技巧,涵盖响应式状态管理、生命周期集成、异步操作封装以及常见陷阱规避,助你写出高质量可复用的Composable代码。
# Vue 3 组合式函数实战指南
在 Vue 3 的组合式 API 诞生之前,我们通常通过 Mixins 来实现逻辑复用,但 Mixins 存在命名冲突、数据来源不明确等痛点。组合式函数(Composable)的出现彻底解决了这些问题,成为 Vue 3 中代码复用的首选方案。
## 一、什么是组合式函数
组合式函数是一个以 `use` 开头的函数,内部利用 Vue 的响应式 API(ref、reactive、computed、watch 等)来封装和复用有状态的逻辑。它的核心思想是将相关的状态和行为封装在一起,对外暴露清晰的接口。
一个简单的示例:
```javascript
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 }
}
```
在组件中使用时只需一行代码:`const { x, y } = useMouse()`,数据来源清晰,不会有命名冲突。
## 二、设计原则
### 1. 单一职责
每个组合式函数应该只关注一个功能点。比如 `useMouse` 只管鼠标位置,`useWindowSize` 只管窗口尺寸。不要把多个不相关的功能塞进同一个函数。
### 2. 接受 Ref 参数
组合式函数的参数应该既支持普通值也支持 ref,这样使用者可以灵活地传入响应式或静态数据:
```javascript
export function useFetch(url) {
// 如果传入的是 ref,使用 toValue 获取值
const resolvedUrl = toValue(url)
// ...
}
```
### 3. 返回值用 ref 而非 reactive
返回 ref 的好处是解构后仍然保持响应性,而 reactive 对象解构后会丢失响应性。
## 三、异步操作封装
处理异步逻辑是组合式函数的常见场景。下面是一个封装 fetch 请求的示例:
```javascript
export function useFetchData(url) {
const data = ref(null)
const error = ref(null)
const loading = ref(false)
async function execute() {
loading.value = true
error.value = null
try {
const res = await fetch(url)
data.value = await res.json()
} catch (e) {
error.value = e.message
} finally {
loading.value = false
}
}
execute()
return { data, error, loading, execute }
}
```
这种方式将 loading、error、data 的管理封装在函数内部,组件只需关心使用结果。
## 四、常见陷阱
### 1. 在 setup 之外使用生命周期钩子
`onMounted`、`onUnmounted` 等钩子只能在 `setup()` 或组合式函数的同步代码中调用,不能在异步回调中使用:
```javascript
// 错误写法
export function useBad() {
setTimeout(() => {
onMounted(() => { }) // 无效!
}, 0)
}
```
### 2. 忘记清理副作用
如果在组合式函数中注册了事件监听、定时器等,务必在 `onUnmounted` 中清理,否则会造成内存泄漏。
### 3. 过度抽象
不是所有逻辑都需要提取为组合式函数。只有当逻辑需要复用或组件过于臃肿时,才考虑提取。过早抽象反而增加复杂度。
## 五、总结
Vue 3 组合式函数是现代 Vue 开发的核心模式。遵循单一职责、接受 ref 参数、返回 ref、正确处理生命周期和副作用清理,就能写出高质量的 Composable。记住:复用需求驱动提取,而非提取驱动复用。