On this page
组合式API逻辑复用实现
如何通过自定义组合函数(composable)实现业务逻辑复用?以鼠标跟踪器或API请求为例,演示将逻辑抽取为独立函数并在多个组件中复用的完整流程。
考察点分析
本题主要考核以下核心能力维度:
- 组合式API机制理解:考察对Vue3组合式API设计理念的掌握,包括逻辑拆分与复用策略
- 响应式系统运用:检验ref/reactive等响应式API的正确使用,及在组合函数中的值传递
- 生命周期整合:评估在自定义hook中正确绑定/清除副作用(如事件监听、异步请求)
- 代码抽象能力:验证业务逻辑解耦能力,包括参数处理、状态暴露、错误边界等工程化实践
具体技术评估点:
- 组合函数的命名规范与结构
- 响应式数据在组件间的状态保持
- 生命周期钩子的正确绑定
- 异步操作的竞态处理(如请求取消)
- TypeScript类型支持实现
技术解析
关键知识点
Composition API Design > 响应式系统 > 生命周期管理 > TypeScript类型推导
原理剖析
组合函数本质是返回响应式状态+函数的闭包封装,利用Vue的setup()执行上下文实现逻辑复用。通过ref维持响应式引用,在onMounted等钩子中绑定原生事件或异步操作,通过onUnmounted进行资源清理,避免内存泄漏。
典型错误包括:
- 直接返回解构对象导致响应式丢失
- 未在卸载阶段移除事件监听
- 异步回调中使用过期状态
常见误区
- 在组合函数内直接修改DOM(违反响应式原则)
- 忘记处理异步操作的错误状态
- 多个组件实例共享同一响应式引用(未使用函数式返回)
问题解答
通过组合函数封装逻辑需遵循以下步骤:
- 创建以
use
开头的函数,使用ref/reactive封装状态 - 在setup阶段执行副作用(如事件绑定)
- 返回组件可用的响应式状态与方法
- 使用toRefs保持解构后响应式
鼠标跟踪器示例:
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
const update = (e) => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
API请求示例:
import { ref } from 'vue'
export function useFetch<T>(url: string) {
const data = ref<T | null>(null)
const error = ref<Error | null>(null)
const loading = ref(false)
const fetchData = async () => {
try {
loading.value = true
const response = await fetch(url)
data.value = await response.json()
} catch (err) {
error.value = err as Error
} finally {
loading.value = false
}
}
return {
data,
error,
loading,
fetchData
}
}
解决方案
编码优化
防抖处理:为鼠标跟踪添加移动节流
import { throttle } from 'lodash-es' const update = throttle((e) => { //...原有逻辑 }, 50)
请求竞态处理:
let controller: AbortController | null = null const fetchData = async () => { if (controller) { controller.abort() } controller = new AbortController() try { const response = await fetch(url, { signal: controller.signal }) //... } finally { controller = null } }
可扩展性建议
- SSR兼容:在组合函数内判断window对象存在性
- 缓存策略:为API请求添加SWR(Stale While Revalidate)逻辑
- 类型扩展:通过泛型支持多样化返回类型
- 低端设备优化:降低鼠标采样频率
深度追问
组合函数与mixins的主要区别?
作用域隔离:组合函数使用显式返回,mixins易导致属性冲突
如何在组合函数中使用生命周期?
直接引入钩子函数,执行时机与组件生命周期同步
TypeScript类型声明最佳实践?
使用泛型约束返回类型,定义明确的接口类型
Last updated 06 Mar 2025, 13:07 +0800 .