前言:为什么我们需要 Composition API?
在 Vue 3 发布两年后的今天,仍有 42% 的开发者坚持使用 Options API(来源:2023 前端生态调研)。本文将通过真实项目案例,带你解锁 Composition API 的进阶用法,解决大型项目中 Options API 导致的代码混乱难题。
一、Options API 的五大开发痛点
1.1 逻辑关注点分离之殇
// Options API 典型结构
export default {
data() {
return { /* 数据A */ }
},
computed: { /* 计算属性A */ },
methods: { /* 方法A */ },
mounted() { /* 生命周期A */ },
// 相关逻辑B分散在不同区域
data() {
return { /* 数据B */ }
},
computed: { /* 计算属性B */ }
}
问题诊断:相关逻辑被强制拆分到不同选项,2000+行组件成为维护噩梦
二、Composition API 核心武器库
2.1 响应式系统三剑客
import { ref, reactive, computed } from 'vue'
// 组合式函数示例
function usePagination() {
const currentPage = ref(1)
const pageSize = ref(10)
const paginationInfo = computed(() => ({
from: (currentPage.value - 1) * pageSize.value,
to: currentPage.value * pageSize.value
}))
return { currentPage, pageSize, paginationInfo }
}
2.2 生命周期 hooks 的正确姿势
import { onMounted, onUnmounted } from 'vue'
function useResizeObserver() {
const width = ref(0)
onMounted(() => {
const observer = new ResizeObserver(entries => {
width.value = entries[0].contentRect.width
})
observer.observe(document.getElementById('target'))
onUnmounted(() => observer.disconnect())
})
return { width }
}
三、实战:电商筛选模块重构
3.1 传统 Options API 实现
export default {
data() {
return {
products: [],
colorFilter: '',
priceRange: [0, 1000],
sortBy: 'price'
}
},
computed: {
filteredProducts() {
// 复杂的过滤排序逻辑
}
},
methods: {
async fetchProducts() {
// API 调用
}
},
mounted() {
this.fetchProducts()
}
}
3.2 Composition API 重构方案
// useProductFilter.ts
export default function () {
const products = ref<Product[]>([])
const filters = reactive({
color: '',
priceRange: [0, 1000],
sortBy: 'price' as 'price' | 'rating'
})
const filteredProducts = computed(() => {
return products.value
.filter(p => p.color === filters.color)
.filter(p => p.price >= filters.priceRange[0] && p.price <= filters.priceRange[1])
.sort((a, b) => filters.sortBy === 'price' ? a.price - b.price : b.rating - a.rating)
})
const fetchProducts = async () => {
products.value = await api.getProducts()
}
onMounted(fetchProducts)
return { products, filters, filteredProducts }
}
重构优势:
- 逻辑聚合度提升 60%
- 可测试性增强
- 类型推导更完善
四、高级模式:组合式函数开发规范
4.1 企业级最佳实践
- 命名规范:
useXxx前缀 + 驼峰命名 - 单一职责:每个函数只关注一个功能点
- 依赖注入:灵活使用 provide/inject
- 类型安全:完善的 TypeScript 支持
// useCart.ts 示例
export default function useCart() {
const cartItems = ref<CartItem[]>([])
const addToCart = (item: Product) => {
// 业务逻辑
}
return {
cartItems,
addToCart
}
}
五、性能优化专项
5.1 计算属性缓存策略
const expensiveCalculation = computed(() => {
// 耗时操作
}, {
// 自定义缓存策略
cache: false
})
5.2 响应式数据分组
// 将高频更新的数据分组
const scrollState = reactive({
position: 0,
direction: 'down',
velocity: 0
})
六、常见问题 Q&A
Q:如何迁移旧项目?
A:推荐渐进式迁移策略:
- 新组件使用 Composition API
- 旧组件按功能模块逐步重构
- 使用 mixin 兼容层
Q:与 TypeScript 的配合技巧?
A:使用 defineComponent + 类型断言:
import { defineComponent } from 'vue'
export default defineComponent({
setup() {
const count = ref<number>(0)
return { count }
}
})
结语
Composition API 不是银弹,但确实是应对复杂前端应用的有力武器。通过本文的实战案例,我们可以看到其在逻辑复用、代码组织和可维护性方面的显著优势。建议从今天开始,在项目中尝试创建一个 composables 目录,开启你的组合式编程之旅。
拓展阅读:
- Vue 官方 Composition API 指南
- VueUse 工具库源码解析
- [TypeScript 4.9 新特性在 Vue 中的应用]
欢迎在评论区交流你的 Composition API 实战经验! 🚀