Composition API 逻辑复用
使用组合式函数实现 Vue 3 逻辑复用
问题
Vue 3 Composition API 如何实现逻辑复用?与 Vue 2 的 mixins 有什么区别?
解答
Composition API 通过**组合式函数(Composables)**实现逻辑复用。组合式函数是以 use 开头的函数,封装并返回响应式状态和方法。
基础示例:useMouse
// composables/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 }
}
<script setup>
import { useMouse } from './composables/useMouse'
// 直接解构使用
const { x, y } = useMouse()
</script>
<template>
<p>鼠标位置: {{ x }}, {{ y }}</p>
</template>
实用示例:useFetch
// composables/useFetch.js
import { ref, watchEffect, toValue } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
const loading = ref(false)
async function fetchData() {
loading.value = true
data.value = null
error.value = null
try {
// toValue() 处理 ref 或 getter
const res = await fetch(toValue(url))
data.value = await res.json()
} catch (e) {
error.value = e
} finally {
loading.value = false
}
}
// 响应式地追踪 url 变化
watchEffect(() => {
fetchData()
})
return { data, error, loading, refetch: fetchData }
}
<script setup>
import { ref } from 'vue'
import { useFetch } from './composables/useFetch'
const userId = ref(1)
// url 变化时自动重新请求
const { data, loading, error } = useFetch(
() => `https://api.example.com/users/${userId.value}`
)
</script>
组合多个 Composables
// composables/useUserStatus.js
import { computed } from 'vue'
import { useFetch } from './useFetch'
import { useLocalStorage } from './useLocalStorage'
export function useUserStatus(userId) {
// 组合其他 composables
const { data: user, loading } = useFetch(`/api/users/${userId}`)
const { value: lastVisit, setValue } = useLocalStorage('lastVisit')
// 基于组合数据计算
const isOnline = computed(() => user.value?.status === 'online')
function recordVisit() {
setValue(new Date().toISOString())
}
return { user, loading, isOnline, lastVisit, recordVisit }
}
与 Mixins 对比
// Vue 2 Mixins - 存在问题
const mousePositionMixin = {
data() {
return { x: 0, y: 0 } // 来源不清晰,可能命名冲突
},
mounted() { /* ... */ }
}
// Vue 3 Composables - 解决问题
const { x, y } = useMouse() // 来源清晰
const { x: mouseX } = useMouse() // 可重命名避免冲突
关键点
- 组合式函数以
use开头,返回响应式状态和方法 - 来源清晰,可通过解构重命名避免冲突
- 支持接收 ref 或 getter 作为参数,实现响应式输入
- 可以自由组合多个 composables,灵活度高
- 相比 mixins:无命名冲突、类型推导友好、逻辑来源明确
目录