前端开发领域,Vue3组合式API(Composition API)重构了组件逻辑组织方式。相比Options API的data/methods/computed分散结构,组合式API允许按功能关注点聚合代码,配合TypeScript类型推断提升类型安全。本文从响应式原理到组件库设计,拆解Vue3生态下的工程化实践。
组合式API核心机制:ref与reactive响应式原理
Vue3响应式系统基于Proxy实现。reactive对对象做深度代理,ref对基本类型值通过.value访问器追踪依赖。理解二者的差异是正确使用组合式API的前提。
import { ref, reactive, watchEffect, toRefs } from 'vue'
// ref适用于基本类型和需要整体替换的值
const count = ref(0)
count.value++
// reactive适用于对象/数组,无需.value
const state = reactive({
user: { name: '张三', age: 25 },
list: []
})
// reactive的局限:解构会失去响应性
const { user } = state // user不再是响应式
// 解决方案:toRefs
const { user: userRef } = toRefs(state) // userRef保持响应式
watchEffect自动追踪回调函数内的响应式依赖,watch显式指定侦听源。选择依据是是否需要旧值访问和惰性执行:
// watchEffect:立即执行,自动追踪依赖
watchEffect(() => {
console.log(`count: ${count.value}, name: ${state.user.name}`)
})
// watch:惰性执行,可获取旧值
watch(
() => state.user.age,
(newAge, oldAge) => {
console.log(`age changed from ${oldAge} to ${newAge}`)
},
{ deep: true, immediate: false }
)
computed基于响应式依赖缓存计算结果,依赖不变时返回缓存值。TypeScript实战中需标注返回类型:
import { ref, computed } from 'vue'
const price = ref(99.5)
const quantity = ref(2)
const total = computed<number>(() => {
return Number((price.value * quantity.value).toFixed(2))
})
自定义组合式函数提取与复用
组合式函数(Composables)是Vue3逻辑复用的核心模式。将状态和操作逻辑封装为以use开头的函数,在多个组件间共享。
通用分页逻辑封装:
// composables/usePagination.ts
import { ref, computed } from 'vue'
interface PaginationOptions {
pageSize?: number
initialPage?: number
}
export function usePagination(totalItems: () => number, options: PaginationOptions = {}) {
const currentPage = ref(options.initialPage ?? 1)
const pageSize = ref(options.pageSize ?? 10)
const totalPages = computed(() =>
Math.ceil(totalItems() / pageSize.value)
)
const paginatedRange = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
return { start, end }
})
function goToPage(page: number) {
if (page >= 1 && page <= totalPages.value) {
currentPage.value = page
}
}
function nextPage() { goToPage(currentPage.value + 1) }
function prevPage() { goToPage(currentPage.value - 1) }
return {
currentPage: computed(() => currentPage.value),
pageSize: computed(() => pageSize.value),
totalPages,
paginatedRange,
goToPage,
nextPage,
prevPage
}
}
组件中使用:
<script setup lang="ts">
import { ref, computed } from 'vue'
import { usePagination } from '@/composables/usePagination'
const allProducts = ref<Product[]>([])
const { currentPage, totalPages, paginatedRange, goToPage } = usePagination(
() => allProducts.value.length,
{ pageSize: 20 }
)
const visibleProducts = computed(() =>
allProducts.value.slice(paginatedRange.value.start, paginatedRange.value.end)
)
</script>
组件设计模式与Props校验
组件库设计需要统一的组件规范。defineProps配合TypeScript接口提供编译时类型检查和运行时校验。
// FormInput.vue
<script setup lang="ts">
import { ref, computed } from 'vue'
interface FormInputProps {
modelValue: string
label: string
type?: 'text' | 'password' | 'email' | 'number'
placeholder?: string
error?: string
disabled?: boolean
rules?: Array<(value: string) => string | true>
}
const props = withDefaults(defineProps<FormInputProps>(), {
type: 'text',
placeholder: '',
error: '',
disabled: false,
rules: () => []
})
const emit = defineEmits<{
'update:modelValue': [value: string]
blur: [event: FocusEvent]
}>()
const inputValue = computed({
get: () => props.modelValue,
set: (val: string) => emit('update:modelValue', val)
})
const validationError = ref('')
function validate() {
for (const rule of props.rules) {
const result = rule(props.modelValue)
if (result !== true) {
validationError.value = result
return false
}
}
validationError.value = ''
return true
}
defineExpose({ validate })
</script>
<template>
<div class="form-field">
<label :for="label">{{ label }}</label>
<input
:id="label"
v-model="inputValue"
:type="type"
:placeholder="placeholder"
:disabled="disabled"
:class="{ error: error || validationError }"
@blur="$emit('blur', $event)"
/>
<span v-if="validationError" class="error-msg">{{ validationError }}</span>
<span v-else-if="error" class="error-msg">{{ error }}</span>
</div>
</template>
defineExpose暴露validate方法给父组件调用,实现表单整体校验时统一触发子组件校验。
TypeScript类型安全与工程化配置
前端工程化配置中,Vite + TypeScript + ESLint + Prettier是Vue3项目标准工具链。vue-tsc提供模板内的类型检查。
tsconfig关键配置:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
响应式布局方面,Vue3配合Tailwind CSS或Unocss可实现高效的样式工程化。组件库设计时建议采用CSS变量定义设计令牌(Design Tokens),实现主题切换:
// design-tokens.ts
export const tokens = {
colors: {
primary: 'var(--color-primary, #3b82f6)',
danger: 'var(--color-danger, #ef4444)',
success: 'var(--color-success, #22c55e)'
},
spacing: {
xs: '4px',
sm: '8px',
md: '16px',
lg: '24px'
},
radius: {
sm: '4px',
md: '8px',
lg: '12px'
}
} as const
组合式API配合TypeScript类型系统,使Vue3项目的代码质量和可维护性达到企业级标准。跨端小程序开发场景下,相同的组合式函数逻辑可直接复用,仅需替换渲染层适配,这体现了Vue3生态架构设计的灵活性。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/vue3-zu-he-shi-api-shi-zhan-zu-jian-luo-ji-fu-yong-yu-xiang/