一、为什么需要组合式API

在Vue2时代,我们习惯使用选项式API来组织组件代码。但随着项目规模扩大,你会发现一个组件可能包含几十个methods、computed和生命周期钩子,相关逻辑分散在各个选项中,就像把衣服乱扔在房间各个角落。

组合式API的出现,就像给你的代码房间买了几个收纳盒。它允许你把相关功能集中在一起,比如这样:

// 技术栈:Vue3 + Composition API
// 用户认证逻辑集合
const useAuth = () => {
  const user = ref(null)
  const isLogin = computed(() => !!user.value)
  
  const login = async (username, password) => {
    // 登录逻辑...
  }
  
  const logout = () => {
    // 登出逻辑...
  }
  
  return { user, isLogin, login, logout }
}

这样组织代码的好处显而易见:相关功能集中管理,便于复用,也更容易理解代码的意图。

二、组合式函数的最佳实践

1. 单一职责原则

每个组合式函数应该只做一件事。比如数据处理和UI逻辑应该分开:

// 技术栈:Vue3 + Composition API
// 数据处理逻辑
const useDataProcessor = (dataSource) => {
  const processedData = ref([])
  
  const processData = () => {
    // 复杂的数据处理逻辑...
  }
  
  return { processedData, processData }
}

// UI控制逻辑
const useUIControl = () => {
  const isModalOpen = ref(false)
  
  const openModal = () => { isModalOpen.value = true }
  const closeModal = () => { isModalOpen.value = false }
  
  return { isModalOpen, openModal, closeModal }
}

2. 合理使用ref和reactive

对于基本类型数据使用ref,对于对象使用reactive:

// 技术栈:Vue3 + Composition API
const useProduct = () => {
  // 基本类型
  const price = ref(0)
  const count = ref(0)
  
  // 对象类型
  const product = reactive({
    name: '',
    description: '',
    category: ''
  })
  
  // 计算总价
  const total = computed(() => price.value * count.value)
  
  return { price, count, product, total }
}

三、复杂场景下的逻辑组织

1. 异步操作的处理

处理异步时,建议使用async/await配合ref来跟踪状态:

// 技术栈:Vue3 + Composition API
const useAsyncData = (url) => {
  const data = ref(null)
  const loading = ref(false)
  const error = ref(null)
  
  const fetchData = async () => {
    loading.value = true
    try {
      const response = await fetch(url)
      data.value = await response.json()
    } catch (err) {
      error.value = err
    } finally {
      loading.value = false
    }
  }
  
  return { data, loading, error, fetchData }
}

2. 跨组件逻辑复用

通过组合式函数实现跨组件逻辑复用:

// 技术栈:Vue3 + Composition API
// 可复用的表单验证逻辑
const useFormValidation = (formData) => {
  const errors = reactive({})
  
  const validate = () => {
    let isValid = true
    
    // 验证用户名
    if (!formData.username) {
      errors.username = '用户名不能为空'
      isValid = false
    }
    
    // 验证密码复杂度
    if (formData.password.length < 6) {
      errors.password = '密码至少6位'
      isValid = false
    }
    
    return isValid
  }
  
  return { errors, validate }
}

四、高级技巧与性能优化

1. 使用watchEffect和watch

根据场景选择合适的响应式API:

// 技术栈:Vue3 + Composition API
const useAutoSave = (formData) => {
  // 自动保存 - 使用watchEffect
  watchEffect(() => {
    if (formData.dirty) {
      debouncedSave(formData)
    }
  })
  
  // 特定字段变化监听 - 使用watch
  watch(
    () => formData.importantField,
    (newVal) => {
      if (newVal === 'danger') {
        showWarning()
      }
    }
  )
}

2. 与Vuex/Pinia配合使用

组合式API与现代状态管理库完美配合:

// 技术栈:Vue3 + Pinia
import { useStore } from '@/stores/main'

const useStoreIntegration = () => {
  const store = useStore()
  
  // 从store获取状态
  const user = computed(() => store.user)
  
  // 调用store action
  const updateProfile = async (profile) => {
    await store.updateUserProfile(profile)
  }
  
  return { user, updateProfile }
}

五、常见问题与解决方案

1. 生命周期钩子的使用

在组合式API中正确使用生命周期:

// 技术栈:Vue3 + Composition API
const useComponentLifecycle = () => {
  onMounted(() => {
    console.log('组件挂载完成')
    setupEventListeners()
  })
  
  onUnmounted(() => {
    console.log('组件即将卸载')
    cleanupEventListeners()
  })
  
  // 只在客户端执行的代码
  if (process.client) {
    useSomeClientOnlyLibrary()
  }
}

2. 类型提示(TypeScript)增强

为组合式函数添加类型定义:

// 技术栈:Vue3 + TypeScript
interface User {
  id: number
  name: string
  email: string
}

const useTypedUser = (): {
  user: Ref<User | null>
  fetchUser: (id: number) => Promise<void>
} => {
  const user = ref<User | null>(null)
  
  const fetchUser = async (id: number) => {
    user.value = await getUserById(id)
  }
  
  return { user, fetchUser }
}

六、实战案例:复杂表单处理

让我们看一个完整的复杂表单处理示例:

// 技术栈:Vue3 + Composition API
const useComplexForm = (initialData) => {
  // 表单数据
  const form = reactive({
    ...initialData,
    dirty: false
  })
  
  // 表单验证
  const { errors, validate } = useFormValidation(form)
  
  // 自动保存
  const { saving, saveError, saveForm } = useAutoSave(form)
  
  // 表单提交
  const submit = async () => {
    if (!validate()) return false
    
    try {
      await saveForm()
      return true
    } catch (error) {
      console.error('提交失败:', error)
      return false
    }
  }
  
  // 监听表单变化
  watch(
    () => form,
    (newVal) => {
      form.dirty = true
    },
    { deep: true }
  )
  
  return { form, errors, saving, saveError, submit }
}

这个示例展示了如何将多个组合式函数组合起来处理复杂表单场景,包括数据管理、验证、自动保存等功能。

七、总结与最佳实践建议

经过上面的探索,我们可以得出一些关键结论:

  1. 组合式API特别适合处理复杂组件逻辑,它让代码组织更加模块化
  2. 每个组合式函数应该保持单一职责,便于测试和复用
  3. 合理使用ref和reactive,基本类型用ref,对象用reactive
  4. 对于复杂异步场景,使用loading/error状态跟踪
  5. 与TypeScript配合能获得更好的开发体验
  6. 可以与现代状态管理库(Pinia/Vuex)无缝集成

在实际项目中,建议从小功能开始尝试组合式API,逐步重构复杂组件。你会发现代码的可维护性和可读性都得到了显著提升。