Vue 3 Composition API 实战指南:从 Options API 到响应式编程

Vue 3 Composition API 实战指南:从 Options API 到响应式编程

随着 Vue 3 的发布,Composition API 成为了 Vue 生态中最重要的新特性之一。它为组件逻辑的组织和复用提供了更灵活的方式,特别适合处理复杂组件的逻辑。本文将深入探讨 Composition API 的核心概念,并通过实际示例展示如何从传统的 Options API 迁移到 Composition API。

1. Composition API 的核心优势

Composition API 的设计目标是解决 Options API 在处理复杂组件逻辑时的局限性:

  • 更好的逻辑复用:通过自定义组合式函数,可以轻松地在多个组件间复用逻辑
  • 更灵活的组织方式:相关逻辑可以组织在一起,而不是分散在 data、methods、computed 等选项中
  • 更好的 TypeScript 支持:完整的类型推断,提供更好的开发体验
  • 更小的打包体积:Tree-shaking 友好,只打包实际使用的 API

2. 基础响应式 API

让我们从最基础的响应式 API 开始:

// Options API 示例
export default {
  data() {
    return {
      count: 0,
      message: "Hello Vue 3"
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  }
}

// Composition API 等价实现
import { ref, computed } from "vue"

export default {
  setup() {
    // 使用 ref 创建响应式数据
    const count = ref(0)
    const message = ref("Hello Vue 3")
    
    // 定义方法
    const increment = () => {
      count.value++
    }
    
    // 计算属性
    const doubleCount = computed(() => count.value * 2)
    
    // 返回模板中需要使用的数据和方法
    return {
      count,
      message,
      increment,
      doubleCount
    }
  }
}

3. 响应式对象与 ref

Vue 3 提供了两种创建响应式数据的方式:

import { ref, reactive, toRefs } from "vue"

export default {
  setup() {
    // ref:适用于基本类型和对象引用
    const count = ref(0)
    const user = ref({ name: "John", age: 30 })
    
    // reactive:专门用于对象
    const state = reactive({
      name: "Alice",
      age: 25,
      address: {
        city: "Shanghai",
        street: "Nanjing Road"
      }
    })
    
    // 使用 toRefs 解构响应式对象
    const { name, age } = toRefs(state)
    
    return {
      count,
      user,
      state,
      name,
      age
    }
  }
}

4. 生命周期钩子

Composition API 中的生命周期钩子以 on 开头:

import { onMounted, onUpdated, onUnmounted, ref } from "vue"

export default {
  setup() {
    const count = ref(0)
    
    // 组件挂载后执行
    onMounted(() => {
      console.log("Component mounted")
      // 可以在这里进行数据初始化或 API 调用
    })
    
    // 组件更新后执行
    onUpdated(() => {
      console.log("Component updated")
    })
    
    // 组件卸载前执行
    onUnmounted(() => {
      console.log("Component unmounted")
      // 清理定时器、事件监听器等
    })
    
    return { count }
  }
}

5. 自定义组合式函数

这是 Composition API 最强大的特性之一:

// useMousePosition.js
import { ref, onMounted, onUnmounted } from "vue"

export function useMousePosition() {
  const x = ref(0)
  const y = ref(0)
  
  const updatePosition = (event) => {
    x.value = event.pageX
    y.value = event.pageY
  }
  
  onMounted(() => {
    window.addEventListener("mousemove", updatePosition)
  })
  
  onUnmounted(() => {
    window.removeEventListener("mousemove", updatePosition)
  })
  
  return { x, y }
}

// 在组件中使用
import { useMousePosition } from "./useMousePosition"

export default {
  setup() {
    const { x, y } = useMousePosition()
    
    return { x, y }
  }
}

6. 实战示例:搜索功能组件

让我们创建一个实用的搜索组件:

// useSearch.js
import { ref, computed, watch } from "vue"

export function useSearch(items, searchKey) {
  const searchQuery = ref("")
  const isLoading = ref(false)
  
  // 计算属性:过滤后的结果
  const filteredItems = computed(() => {
    if (!searchQuery.value) return items.value
    
    return items.value.filter(item => 
      item[searchKey].toLowerCase().includes(searchQuery.value.toLowerCase())
    )
  })
  
  // 监听搜索词变化,可以添加防抖
  watch(searchQuery, (newQuery) => {
    if (newQuery.length > 2) {
      // 这里可以添加 API 调用逻辑
      console.log(`Searching for: ${newQuery}`)
    }
  })
  
  // 清空搜索
  const clearSearch = () => {
    searchQuery.value = ""
  }
  
  return {
    searchQuery,
    filteredItems,
    isLoading,
    clearSearch
  }
}

// SearchComponent.vue
import { ref } from "vue"
import { useSearch } from "./useSearch"

export default {
  setup() {
    const items = ref([
      { id: 1, name: "Vue.js", category: "Framework" },
      { id: 2, name: "React", category: "Library" },
      { id: 3, name: "Angular", category: "Framework" },
      { id: 4, name: "Svelte", category: "Compiler" }
    ])
    
    const { searchQuery, filteredItems, clearSearch } = useSearch(items, "name")
    
    return {
      searchQuery,
      filteredItems,
      clearSearch
    }
  }
}

7. 与 Options API 的混合使用

Vue 3 支持 Composition API 和 Options API 混合使用:

export default {
  // Options API
  data() {
    return {
      legacyData: "I am from Options API"
    }
  },
  
  methods: {
    legacyMethod() {
      console.log(this.legacyData)
    }
  },
  
  // Composition API
  setup() {
    const newData = ref("I am from Composition API")
    
    const newMethod = () => {
      console.log(newData.value)
    }
    
    return {
      newData,
      newMethod
    }
  }
}

8. 最佳实践

  1. 合理组织逻辑:将相关的响应式数据、计算属性和方法放在一起
  2. 使用自定义组合式函数:提取可复用的逻辑到独立的函数中
  3. 注意响应式丢失:解构响应式对象时使用 toRefs
  4. 类型安全:充分利用 TypeScript 的类型推断
  5. 渐进式迁移:可以在现有项目中逐步引入 Composition API

总结

Composition API 为 Vue 开发带来了新的可能性。虽然学习曲线比 Options API 稍陡,但它提供了更好的逻辑组织方式、更强的类型支持和更灵活的代码复用机制。对于新项目,建议直接使用 Composition API;对于现有项目,可以采用渐进式迁移策略。

通过本文的示例,你应该已经掌握了 Composition API 的核心概念和实际应用。在实际开发中,根据项目需求和团队习惯选择合适的 API 风格,最重要的是保持代码的可维护性和可读性。

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

请登录后发表评论

    暂无评论内容