Skip to content

组合逻辑复用(自定义 Hook)

组合逻辑复用是 Vue 3 组合式 API 最强大的特性之一,它允许你将组件逻辑提取到可复用的函数中(称为 "自定义 Hook"),彻底解决了 Vue 2 中 mixins 带来的所有问题。

什么是自定义 Hook?

自定义 Hook 是一个使用 Vue 组合式 API 的函数,它可以:

  • 封装和复用状态逻辑
  • 包含响应式状态、计算属性、方法等
  • 像普通函数一样被多个组件调用
  • 实现比 mixins 更清晰、更安全的逻辑复用

基本结构

一个典型的自定义 Hook 包含以下部分:

javascript
// useFeature.js
import { ref, computed, onMounted } from 'vue'

export default function useFeature() {
  // 1. 状态声明
  const count = ref(0)
  
  // 2. 计算属性
  const doubleCount = computed(() => count.value * 2)
  
  // 3. 方法
  function increment() {
    count.value++
  }
  
  // 4. 生命周期/副作用
  onMounted(() => {
    console.log('Hook mounted')
  })
  
  // 5. 返回暴露给组件的值
  return {
    count,
    doubleCount,
    increment
  }
}

在组件中使用

vue
<script setup>
import useFeature from './useFeature'

const { count, doubleCount, increment } = useFeature()
</script>

<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Double: {{ doubleCount }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

核心优势

相比 Mixins 的优势

特性Mixins自定义 Hook
命名冲突容易发生无(明确命名空间)
隐式依赖难以追踪显式导入
可组合性有限高度灵活
类型支持困难天然支持 TS
代码组织分散逻辑集中

实际优势

  • 明确的数据来源:知道每个状态/方法来自哪个 Hook
  • 按需使用:可以选择性使用 Hook 的部分功能
  • 嵌套组合:可以组合多个 Hook 创建更复杂的逻辑

进阶用法

接受参数

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

组合多个 Hook

javascript
// useUserDashboard.js
export default function useUserDashboard(userId) {
  const { user, loading } = useUser(userId)
  const { posts } = useUserPosts(userId)
  const { preferences } = useUserPreferences(userId)
  
  return {
    user,
    posts,
    preferences,
    loading
  }
}

副作用清理

javascript
// useEventListener.js
export default function useEventListener(target, event, callback) {
  onMounted(() => target.addEventListener(event, callback))
  onUnmounted(() => target.removeEventListener(event, callback))
}

最佳实践

命名约定

  • 始终以 use 开头(如 useFetch, useMousePosition
  • 使用 camelCase 命名法

组织方式

src/
  hooks/
    useFetch.js
    useLocalStorage.js
    useMouse.js

性能优化

  • 避免在 Hook 中创建不必要的响应式对象
  • 对于不常变化的值,使用 shallowRefshallowReactive
  • 使用 computed 缓存计算结果

TypeScript 支持

typescript
// useCounter.ts
interface UseCounterReturn {
  count: Ref<number>
  increment: () => void
  reset: () => void
}

export default function useCounter(initialValue = 0): UseCounterReturn {
  const count = ref(initialValue)
  
  function increment() {
    count.value++
  }
  
  function reset() {
    count.value = initialValue
  }
  
  return {
    count,
    increment,
    reset
  }
}

实际案例

鼠标位置追踪

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

export default function useMousePosition() {
  const x = ref(0)
  const y = ref(0)
  
  function update(e) {
    x.value = e.pageX
    y.value = e.pageY
  }
  
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))
  
  return { x, y }
}

本地存储同步

javascript
// useLocalStorage.js
import { ref, watch } from 'vue'

export default function useLocalStorage(key, initialValue) {
  const stored = localStorage.getItem(key)
  const data = ref(stored ? JSON.parse(stored) : initialValue)
  
  watch(data, (newValue) => {
    localStorage.setItem(key, JSON.stringify(newValue))
  }, { deep: true })
  
  return data
}

与 Vuex/Pinia 的关系

  • 自定义 Hook:适合UI相关的局部状态逻辑

  • 状态管理库:适合全局共享的状态

  • 可以结合使用:

    javascript
    // 在 Hook 中使用 Pinia
    import { useCartStore } from '@/stores/cart'
    
    export default function useCheckout() {
      const cart = useCartStore()
      
      function checkout() {
        // 使用 store 中的状态和方法
      }
      
      return { checkout }
    }

总结

Vue 3 的自定义 Hook 系统提供了:

  1. 更清晰的逻辑复用 - 告别 mixins 的混乱
  2. 更好的代码组织 - 相关逻辑集中在一起
  3. 更强的类型支持 - 完美配合 TypeScript
  4. 更高的灵活性 - 可以组合和嵌套使用

通过合理使用自定义 Hook,你可以:

  • 大幅减少重复代码
  • 提高代码可维护性
  • 创建高度可复用的逻辑单元
  • 构建更健壮的 Vue 应用架构
编程洪同学服务平台是一个广泛收集编程相关内容和资源,旨在满足编程爱好者和专业开发人员的需求的网站。无论您是初学者还是经验丰富的开发者,都可以在这里找到有用的信息和资料,我们将助您提升编程技能和知识。
专业开发
高端定制
售后无忧
站内资源均为本站制作或收集于互联网等平台,如有侵权,请第一时间联系本站,敬请谅解!本站资源仅限于学习与参考,严禁用于各种非法活动,否则后果自行负责,本站概不承担!