Administrator
Administrator
发布于 2025-07-16 / 3 阅读

Vue 3 的组合式 API的优点

Vue 3 的组合式 API 相比选项式 API 的核心优势在于逻辑复用性和代码组织方式。下面通过一个具体示例说明为什么它更灵活、更逻辑化:

场景需求

假设我们需要在组件中实现:

  1. 跟踪鼠标位置
  2. 计数器功能
  3. 窗口尺寸变化监听

选项式 API 实现 (Vue 2 风格)

export default {
  data() {
    return {
      x: 0,
      y: 0,
      count: 0,
      windowWidth: 0
    }
  },
  methods: {
    updateMouse(e) {
      this.x = e.pageX
      this.y = e.pageY
    },
    increment() {
      this.count++
    },
    updateWindowSize() {
      this.windowWidth = window.innerWidth
    }
  },
  mounted() {
    window.addEventListener('mousemove', this.updateMouse)
    window.addEventListener('resize', this.updateWindowSize)
    this.updateWindowSize()
  },
  beforeUnmount() {
    window.removeEventListener('mousemove', this.updateMouse)
    window.removeEventListener('resize', this.updateWindowSize)
  }
}

问题分析:

  1. 逻辑碎片化:鼠标跟踪、计数器和窗口尺寸的逻辑分散在 datamethods 和生命周期钩子中
  2. 复用困难:无法直接复用鼠标跟踪或窗口监听逻辑
  3. 代码膨胀:当功能增加时,组件会变得臃肿难维护

组合式 API 实现 (Vue 3 风格)

import { ref, onMounted, onBeforeUnmount } from 'vue'

// 1. 鼠标位置逻辑(可复用的组合函数)
function useMouse() {
  const x = ref(0)
  const y = ref(0)
  
  const update = e => {
    x.value = e.pageX
    y.value = e.pageY
  }

  onMounted(() => window.addEventListener('mousemove', update))
  onBeforeUnmount(() => window.removeEventListener('mousemove', update))

  return { x, y }
}

// 2. 窗口尺寸逻辑(可复用的组合函数)
function useWindowSize() {
  const width = ref(window.innerWidth)
  
  const update = () => width.value = window.innerWidth

  onMounted(() => window.addEventListener('resize', update))
  onBeforeUnmount(() => window.removeEventListener('resize', update))

  return { width }
}

// 3. 组件中组合这些功能
export default {
  setup() {
    const count = ref(0)
    const { x, y } = useMouse()
    const { width } = useWindowSize()

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

    return { 
      count,
      increment,
      x, 
      y,
      width
    }
  }
}

组合式 API 的优势解析:

1. 逻辑关注点分离

  • 传统方式:相同功能的代码分散在不同选项块中(data + methods + lifecycle hooks
  • 组合式:将鼠标跟踪、窗口尺寸等独立逻辑封装成自包含函数,组件只需组合这些函数

2. 真正的逻辑复用

  • 创建 useMouse()useWindowSize()可复用逻辑单元
  • 在任何组件中只需一行代码即可引入完整功能:
    // 在其他组件复用
    import useMouse from '@/composables/useMouse'
    
    export default {
      setup() {
        const { x, y } = useMouse()
        // ...
      }
    }
    

3. 更灵活的代码组织

  • 功能逻辑而非选项类型组织代码
  • 新增功能时只需添加新的组合函数,不破坏现有结构
  • 删除功能时直接移除对应的组合函数调用

4. 更好的类型推导

  • 组合函数天然支持 TypeScript 类型推导
  • 选项式 API 的 this 上下文导致类型推导困难

5. 逻辑解耦

  • 每个组合函数都是独立单元,不依赖组件上下文
  • 方便单独测试:useMouse() 的逻辑可脱离组件测试

对比总结

维度 选项式 API 组合式 API
代码组织 按选项类型分散 按功能逻辑集中
复用性 mixins/作用域插槽 直接函数调用
可读性 需在不同区块跳转阅读 同一功能代码集中在一起
复杂度 大组件难维护 通过组合函数保持简洁
TS支持 有限 完整类型支持

关键理解:组合式 API 不是简单的把代码移到 setup() 里,而是通过组合函数(composables)实现原子化逻辑封装,这才是"组合式"的核心含义。

实际开发中,你可以:

  1. 将通用逻辑提取到 composables 目录
  2. 复杂组件拆分为多个组合函数
  3. 使用社区成熟组合库(如 VueUse

这种模式特别适合中大型项目,随着功能增加,优势会愈加明显。