Vue3 Composition API 项目实战:组合式函数封装与复用技巧

一、组合式函数核心概念

组合式函数(Composable)是 Vue3 的核心创新,它通过函数式封装实现响应式逻辑的复用。与传统选项式 API 相比具有以下优势:

  1. 高复用性:逻辑单元可跨组件复用
  2. 强内聚性:相关逻辑集中管理
  3. 灵活组合:多个函数可自由组合使用
  4. 类型友好:天然支持 TypeScript 类型推断

数学表达示例:
当组件复杂度 $C$ 随功能点 $n$ 增长时,组合式函数可降低复杂度增量:
$$\Delta C = k \cdot \log(n) \quad (k < 1)$$

二、封装技巧精要
  1. 单一职责原则

    • 每个函数只处理单一功能
    • 避免超过 3 个响应式状态源
  2. 响应式状态管理

    import { ref, computed } from 'vue'
    
    // 计数器函数封装
    export function useCounter(initial = 0) {
      const count = ref(initial)
      const double = computed(() => count.value * 2)
      
      const increment = () => count.value++
      const reset = () => count.value = initial
    
      return { count, double, increment, reset }
    }
    

  3. 生命周期集成

    import { onMounted, onUnmounted } from 'vue'
    
    export function useEventListener(target, event, callback) {
      onMounted(() => target.addEventListener(event, callback))
      onUnmounted(() => target.removeEventListener(event, callback))
    }
    

三、高级复用模式
  1. 参数化配置

    export function useFetch(url, options = {}) {
      const data = ref(null)
      const error = ref(null)
      
      fetch(url, options)
        .then(res => data.value = res.json())
        .catch(err => error.value = err)
    
      return { data, error }
    }
    

  2. 组合嵌套

    export function useUserDashboard(userId) {
      const { data: user } = useFetch(`/api/users/${userId}`)
      const { data: orders } = useFetch(`/api/orders?user=${userId}`)
      const notifications = useWebSocket('/notifications')
    
      return { user, orders, notifications }
    }
    

  3. 状态共享

    // sharedState.js
    import { reactive } from 'vue'
    export const globalState = reactive({ theme: 'light' })
    
    // 使用处
    import { globalState } from './sharedState'
    const toggleTheme = () => { 
      globalState.theme = globalState.theme === 'light' ? 'dark' : 'light'
    }
    

四、实战案例:鼠标跟踪器
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouseTracker() {
  const x = ref(0)
  const y = ref(0)
  const distance = ref(0)

  const update = e => {
    x.value = e.clientX
    y.value = e.clientY
    // 计算距中心点距离: $d = \sqrt{x^2 + y^2}$
    distance.value = Math.sqrt(
      Math.pow(window.innerWidth/2 - x.value, 2) + 
      Math.pow(window.innerHeight/2 - y.value, 2)
    )
  }

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

  return { x, y, distance }
}

组件使用示例:

<script setup>
import { useMouseTracker } from './mouseTracker'

const { x, y, distance } = useMouseTracker()
</script>

<template>
  <div>
    <p>坐标: ({{ x }}, {{ y }})</p>
    <p>距中心距离: {{ distance.toFixed(2) }}px</p>
  </div>
</template>

五、最佳实践总结
  1. 命名规范:统一使用 useXxx 前缀
  2. 依赖管理:显式声明 props 参数
  3. 副作用清理:确保注销事件监听器
  4. 测试策略:单独测试组合式函数
  5. 文档输出:使用 JSDoc 生成类型提示

组合式函数将响应式逻辑的复用率 $R$ 提升至:
$$R = 1 - \frac{L_c}{L_t} \quad (L_c: 封装逻辑量, L_t: 总逻辑量)$$
当 $L_c/L_t > 0.7$ 时,代码复用效益显著提升

通过合理封装,可使业务逻辑复用率提升 60% 以上,同时降低组件复杂度 40%,大幅提升大型项目的可维护性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐