Vue 3 Composition API 实战指南:从 Options API 到 Composition API 的平滑迁移

Vue 3 Composition API 实战指南:从 Options API 到 Composition API 的平滑迁移

随着 Vue 3 的发布,Composition API 成为了 Vue 生态中最重要的新特性之一。它不仅提供了更好的代码组织方式,还解决了 Options API 在大型项目中遇到的一些痛点。本文将深入探讨 Composition API 的核心概念,并通过实际示例展示如何从 Options API 平滑迁移到 Composition API。

1. Composition API 的核心优势

Composition API 的设计初衷是为了解决 Options API 在复杂组件中的局限性:

  • 更好的逻辑复用:通过组合函数(composables)实现逻辑的封装和复用
  • 更灵活的类型推导:TypeScript 支持更加完善
  • 更清晰的代码组织:相关逻辑可以组织在一起,而不是分散在不同的选项中

2. 基础用法对比

让我们先看一个简单的计数器组件,分别用 Options API 和 Composition API 实现:

Options API 实现:

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    }
  }
}
</script>

Composition API 实现:

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const count = ref(0)

const increment = () => {
  count.value++
}

const decrement = () => {
  count.value--
}
</script>

3. 响应式系统:ref vs reactive

Composition API 提供了两种创建响应式数据的方式:

import { ref, reactive } from 'vue'

// ref - 适用于基本类型和对象引用
const count = ref(0)
const user = ref({ name: 'John', age: 25 })

// reactive - 仅适用于对象
const state = reactive({
  count: 0,
  user: { name: 'John', age: 25 }
})

// 访问 ref 的值需要使用 .value
console.log(count.value) // 0

// 访问 reactive 对象直接使用属性
console.log(state.count) // 0

4. 计算属性和侦听器

Composition API 中的 computed 和 watch 函数提供了更灵活的使用方式:

import { ref, computed, watch } from 'vue'

const count = ref(0)
const doubleCount = computed(() => count.value * 2)

// 侦听单个响应式源
watch(count, (newValue, oldValue) => {
  console.log(`count changed from ${oldValue} to ${newValue}`)
})

// 侦听多个响应式源
watch([count, doubleCount], ([newCount, newDouble], [oldCount, oldDouble]) => {
  console.log(`Count: ${oldCount} → ${newCount}`)
  console.log(`Double: ${oldDouble} → ${newDouble}`)
})

5. 自定义组合函数(Composables)

这是 Composition API 最强大的特性之一。我们可以将相关逻辑封装成可复用的函数:

// useCounter.js
export function useCounter(initialValue = 0) {
  const count = ref(initialValue)
  
  const increment = () => {
    count.value++
  }
  
  const decrement = () => {
    count.value--
  }
  
  const reset = () => {
    count.value = initialValue
  }
  
  return {
    count,
    increment,
    decrement,
    reset
  }
}

// 在组件中使用
import { useCounter } from './useCounter'

const { count, increment, decrement } = useCounter(10)

6. 生命周期钩子

Composition API 中的生命周期钩子以函数形式提供:

import { onMounted, onUpdated, onUnmounted } from 'vue'

onMounted(() => {
  console.log('组件已挂载')
  // 执行初始化操作
})

onUpdated(() => {
  console.log('组件已更新')
})

onUnmounted(() => {
  console.log('组件已卸载')
  // 清理工作
})

7. 实际应用示例:搜索功能

让我们创建一个实用的搜索功能组合函数:

// useSearch.js
export function useSearch(items, searchKey) {
  const searchQuery = ref('')
  
  const filteredItems = computed(() => {
    if (!searchQuery.value) return items.value
    
    const query = searchQuery.value.toLowerCase()
    return items.value.filter(item => {
      const value = item[searchKey]
      return value && value.toString().toLowerCase().includes(query)
    })
  })
  
  const clearSearch = () => {
    searchQuery.value = ''
  }
  
  return {
    searchQuery,
    filteredItems,
    clearSearch
  }
}

// 在组件中使用
const items = ref([
  { id: 1, name: 'Apple', category: 'Fruit' },
  { id: 2, name: 'Banana', category: 'Fruit' },
  { id: 3, name: 'Carrot', category: 'Vegetable' }
])

const { searchQuery, filteredItems, clearSearch } = useSearch(items, 'name')

8. 迁移策略建议

对于现有项目,建议采用渐进式迁移策略:

  1. 新组件使用 Composition API:所有新开发的组件都使用 Composition API
  2. 复杂组件优先迁移:先迁移那些逻辑复杂、难以维护的组件
  3. 使用组合函数封装逻辑:将可复用的逻辑提取为组合函数
  4. 混合使用:在同一个项目中可以同时使用两种 API

9. 性能优化技巧

使用 Composition API 时,可以注意以下性能优化点:

// 使用 shallowRef 避免深度响应式转换
import { shallowRef } from 'vue'
const largeObject = shallowRef({ /* 大型对象 */ })

// 使用 watchEffect 自动追踪依赖
import { watchEffect } from 'vue'
watchEffect(() => {
  // 自动追踪所有访问的响应式数据
  console.log(`Count: ${count.value}, Double: ${doubleCount.value}`)
})

// 使用 markRaw 标记非响应式对象
import { markRaw } from 'vue'
const staticConfig = markRaw({
  apiUrl: 'https://api.example.com',
  timeout: 5000
})

总结

Composition API 为 Vue 开发带来了全新的可能性。它不仅解决了 Options API 在大型应用中的局限性,还通过组合函数提供了更好的逻辑复用能力。虽然学习曲线相对较陡,但一旦掌握,将极大提升开发效率和代码质量。

建议开发者从简单的组件开始尝试 Composition API,逐步掌握其核心概念。随着 Vue 3 生态的成熟,Composition API 将成为 Vue 开发的主流选择。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容