Vue3组合式API实战:构建可复用的业务逻辑层架构



Vue3的组合式API(Composition API)彻底改变了组件逻辑的组织方式。相比选项式API将同一业务逻辑分散在data、methods、computed中的割裂体验,组合式API允许按功能维度聚合代码,让逻辑复用从混入mixin升级为组合函数composable。本文从实际项目出发,演示如何用组合式API构建清晰的业务逻辑层。

Composable函数设计原则与分层策略

Composable是Vue3逻辑复用的基本单元。好的Composable应该满足三个条件:单一职责、显式依赖注入、返回值语义清晰。在大型项目中,Composable按职责分为三层:

– 基础层:封装浏览器API、第三方SDK,如useLocalStorage、useIntersectionObserver
– 业务层:封装领域逻辑,如useCart、useUserPermission
– 页面层:组合多个业务Composable,仅在页面组件中使用

基础层Composable示例:

import { ref, watch } from 'vue'
export function useLocalStorage(key, defaultValue) {
const data = ref(defaultValue)
const stored = localStorage.getItem(key)
if (stored) { try { data.value = JSON.parse(stored) } catch {} }
watch(data, (val) => {
localStorage.setItem(key, JSON.stringify(val))
}, { deep: true })
return { data }
}

这个Composable只做一件事:在ref和localStorage之间建立双向同步。不依赖任何外部状态,测试时也只需mock localStorage。

异步数据获取Composable的标准化封装

前端开发中异步请求是最高频的操作。封装统一的useFetch可以消除组件中的重复样板代码:

export function useFetch(url, options) {
const data = shallowRef(null)
const error = ref(null)
const loading = ref(false)
const execute = async () => {
loading.value = true
error.value = null
try {
const resolvedUrl = typeof url === 'function' ? url() : url
const res = await fetch(resolvedUrl, options)
if (!res.ok) throw new Error('HTTP ' + res.status)
data.value = await res.json()
} catch (e) { error.value = e }
finally { loading.value = false }
}
return { data, error, loading, execute }
}

使用shallowRef避免深层响应式对大JSON对象的性能开销。调用方在组件中按需使用。

复杂表单状态管理的Composable模式

表单是前端最复杂的交互场景之一:字段校验、联动逻辑、提交防重、脏检查都需要处理。将表单逻辑抽离为独立Composable后,组件模板只负责渲染:

export function useForm(initialValues, rules) {
const form = reactive({ ...initialValues })
const errors = reactive({})
const submitting = ref(false)
const validate = (field) => {
const fields = field ? [field] : Object.keys(rules)
let valid = true
for (const f of fields) {
const fieldRules = rules[f] ?? []
errors[f] = []
for (const rule of fieldRules) {
const msg = rule(form[f], form)
if (msg) { errors[f].push(msg); valid = false }
}
}
return valid
}
const isDirty = computed(() => JSON.stringify(form) !== JSON.stringify(initialValues))
const submit = async (fn) => {
if (submitting.value) return
if (!validate()) return
submitting.value = true
try { await fn({ ...form }) } finally { submitting.value = false }
}
return { form, errors, submitting, isDirty, validate, submit }
}

组件中使用时只需传入初始值和校验规则,所有状态管理和提交流程由Composable统一处理。

Composable单元测试策略与最佳实践

Composable的优势之一是可独立测试。使用@vue/test-utils的withSetup工具在测试中运行Composable:

test('useFetch handles success', async () => {
global.fetch = vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ id: 1 }) })
const { data, loading, execute } = withSetup(() => useFetch('/api/test'))
await execute()
expect(data.value).toEqual({ id: 1 })
})

测试Composable时避免依赖真实DOM和真实API,fetch用vi.fn()模拟,响应式依赖由withSetup自动管理生命周期。每个Composable的测试文件控制在20个用例以内,覆盖正常流、异常流和边界条件。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/vue3-zu-he-shi-api-shi-zhan-gou-jian-ke-fu-yong-de-ye-wu/

(0)
小编小编
上一篇 15小时前
下一篇 15小时前

相关推荐