深度解析:在vue3中使用自定义Hooks

在Vue 3中,Hooks主要基于Composition API实现,是一套用于组织和复用组件逻辑的函数。它们摆脱了Options API中"按选项分类"的限制,允许按"逻辑关注点"组织代码,大幅提升了代码的可复用性和可维护性。

一、基础Hooks(Composition API核心)

Vue 3内置了一系列基础Hooks,用于实现响应式、生命周期管理等核心功能。

1. 响应式相关Hooks

用于创建和管理响应式数据。

Hook 作用 示例
ref 创建基本类型(或对象)的响应式数据(通过.value访问) javascript import { ref } from 'vue' const count = ref(0) // 读取:count.value // 修改:count.value++
reactive 创建对象类型的响应式数据(直接访问属性) javascript import { reactive } from 'vue' const user = reactive({ name: '张三', age: 20 }) // 读取:user.name // 修改:user.age = 21
computed 创建计算属性(依赖响应式数据,自动缓存结果) javascript import { ref, computed } from 'vue' const count = ref(1) const doubleCount = computed(() => count.value * 2) // 访问:doubleCount.value
watch 监听响应式数据变化(显式指定监听源) javascript import { ref, watch } from 'vue' const count = ref(0) watch(count, (newVal, oldVal) => { console.log(`count从${oldVal}变成了${newVal}`) })
watchEffect 自动追踪响应式依赖,依赖变化时执行(无需显式指定源) javascript import { ref, watchEffect } from 'vue' const count = ref(0) watchEffect(() => { console.log(`count当前值:${count.value}`) // 自动追踪count })
2. 生命周期Hooks

对应Vue 2的生命周期函数,在Composition API中以函数形式存在,需在setup<script setup>中使用。

Hook 对应Vue 2生命周期 作用
onMounted mounted 组件挂载后执行
onUpdated updated 组件更新后执行
onUnmounted unmounted 组件卸载后执行
onBeforeMount beforeMount 组件挂载前执行
onBeforeUpdate beforeUpdate 组件更新前执行
onBeforeUnmount beforeDestroy 组件卸载前执行
onErrorCaptured - 捕获子组件错误时执行
onActivated - 缓存组件(<KeepAlive>)激活时执行
onDeactivated - 缓存组件失活时执行

示例

代码语言:javascript


AI代码解释

javascript 复制代码
import { onMounted, onUnmounted } from 'vue'

onMounted(() => {
  console.log('组件挂载完成')
  // 例如:初始化定时器、事件监听
})

onUnmounted(() => {
  console.log('组件卸载完成')
  // 例如:清除定时器、事件监听
})
3. 其他基础Hooks
Hook 作用 示例
toRef 将响应式对象的属性转为ref(保持响应式关联) javascript import { reactive, toRef } from 'vue' const user = reactive({ name: '张三' }) const nameRef = toRef(user, 'name') // 修改nameRef会同步到user.name
toRefs 将响应式对象的所有属性转为ref对象(用于解构) javascript import { reactive, toRefs } from 'vue' const user = reactive({ name: '张三', age: 20 }) const { name, age } = toRefs(user) // 解构后仍保持响应式
shallowRef 创建"浅响应式"数据(仅顶层响应式) javascript import { shallowRef } from 'vue' const obj = shallowRef({ a: 1 }) // 修改obj.value.a不会触发更新,需重新赋值obj.value才会更新
shallowReactive 创建"浅响应式"对象(仅顶层属性响应式) javascript import { shallowReactive } from 'vue' const obj = shallowReactive({ a: 1, b: { c: 2 } }) // 修改obj.a会触发更新,修改obj.b.c不会
readonly 创建只读响应式数据(禁止修改) javascript import { reactive, readonly } from 'vue' const user = reactive({ name: '张三' }) const readOnlyUser = readonly(user) // 修改readOnlyUser.name会报错

二、自定义Hooks

自定义Hooks是Vue Hooks的核心价值所在,用于封装可复用的逻辑(如数据请求、本地存储、事件监听等),命名通常以use开头(如useFetchuseLocalStorage)。

1. 自定义Hooks的特点
  • 必须是函数,且命名以use开头(约定);
  • 内部可调用Vue内置Hooks(如refonMounted);
  • 可返回响应式数据、方法等,供组件使用。
2. 常用自定义Hooks示例
示例1:useFetch(封装API请求逻辑)

代码语言:javascript


AI代码解释

csharp 复制代码
// hooks/useFetch.js
import { ref, onMounted, watch } from 'vue'

export function useFetch(url) {
  const data = ref(null)
  const loading = ref(false)
  const error = ref(null)

  // 定义请求方法
  const fetchData = async () => {
    loading.value = true
    error.value = null
    try {
      const res = await fetch(url)
      data.value = await res.json()
    } catch (err) {
      error.value = err.message
    } finally {
      loading.value = false
    }
  }

  // 组件挂载时请求
  onMounted(fetchData)

  // 监听url变化,自动重新请求
  watch(url, fetchData)

  // 返回响应式数据和方法
  return { data, loading, error, refetch: fetchData }
}

组件中使用

代码语言:vue


AI代码解释

xml 复制代码
<template>
  <div>
    <div v-if="loading">加载中...</div>
    <div v-if="error">错误:{{ error }}</div>
    <ul v-if="data">
      <li v-for="item in data" :key="item.id">{{ item.name }}</li>
    </ul>
    <button @click="refetch">重新加载</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useFetch } from './hooks/useFetch'

const url = ref('https://api.example.com/data')
const { data, loading, error, refetch } = useFetch(url)
</script>
示例2:useLocalStorage(封装本地存储逻辑)

代码语言:javascript


AI代码解释

javascript 复制代码
// hooks/useLocalStorage.js
import { ref, watch } from 'vue'

export function useLocalStorage(key, defaultValue) {
  // 从localStorage读取初始值
  const value = ref(
    JSON.parse(localStorage.getItem(key)) || defaultValue
  )

  // 监听值变化,同步到localStorage
  watch(value, (newVal) => {
    localStorage.setItem(key, JSON.stringify(newVal))
  }, { deep: true }) // deep: true 确保对象修改也能被监听

  // 返回响应式数据和清除方法
  return {
    value,
    clear: () => {
      value.value = defaultValue
      localStorage.removeItem(key)
    }
  }
}

组件中使用

代码语言:vue


AI代码解释

xml 复制代码
<script setup>
import { useLocalStorage } from './hooks/useLocalStorage'

// 存储用户偏好设置
const { value: userSettings, clear } = useLocalStorage(
  'user-settings',
  { theme: 'light', notifications: true }
)

// 修改值会自动同步到localStorage
userSettings.value.theme = 'dark'

// 清除存储
// clear()
</script>
示例3:useWindowSize(监听窗口大小变化)

代码语言:javascript


AI代码解释

javascript 复制代码
// hooks/useWindowSize.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useWindowSize() {
  const width = ref(window.innerWidth)
  const height = ref(window.innerHeight)

  const updateSize = () => {
    width.value = window.innerWidth
    height.value = window.innerHeight
  }

  // 挂载时监听窗口 resize 事件
  onMounted(() => {
    window.addEventListener('resize', updateSize)
  })

  // 卸载时移除监听(避免内存泄漏)
  onUnmounted(() => {
    window.removeEventListener('resize', updateSize)
  })

  return { width, height }
}

组件中使用

代码语言:vue


AI代码解释

xml 复制代码
<template>
  <div>窗口大小:{{ width }} × {{ height }}</div>
</template>

<script setup>
import { useWindowSize } from './hooks/useWindowSize'
const { width, height } = useWindowSize()
</script>

三、Hooks使用最佳实践

  1. 单一职责 :一个自定义Hooks只封装一个逻辑关注点(如useFetch只处理请求,useLocalStorage只处理本地存储)。
  2. 避免过度封装:简单逻辑无需抽为Hooks,避免增加复杂度。
  3. 清理副作用 :在onUnmounted中清除定时器、事件监听等,避免内存泄漏。
  4. 命名规范 :自定义Hooks以use开头(如useFormuseAuth),便于识别。
  5. 组合复用 :多个Hooks可相互组合使用(如useFetch中可调用useLocalStorage缓存数据)。

总结

Vue Hooks(基于Composition API)通过函数式编程的方式,解决了Options API中逻辑复用难、代码分散的问题。内置Hooks提供了响应式、生命周期等基础能力,而自定义Hooks则是实现逻辑复用的核心,让组件代码更简洁、可维护性更高。

实际开发中,可根据业务场景封装更多自定义Hooks(如表单处理useForm、权限控制usePermission等),大幅提升开发效率。

相关推荐
hxmmm2 小时前
js中生成器和迭代器
前端
黄交大彭于晏3 小时前
UniApp 全局通知功能实现
前端·vue.js·uni-app
sTone873753 小时前
Android核心概念(一)minSdkVersion targetSdkVersion compileSdkVersion
android·前端
林太白3 小时前
八大数据结构
前端·后端·算法
一 乐3 小时前
流浪动物救助|流浪猫狗救助|基于Springboot+vue的流浪猫狗救助平台设计与实现(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设
火星数据-Tina3 小时前
Python + WebSocket 实现实时体育比分系统(含数据库设计与前端演示)
开发语言·前端
国思RDIF框架3 小时前
国思RDIF低代码快速开发框架 v6.2.2版本发布
前端·vue.js·后端
oil欧哟4 小时前
Agent 设计与上下文工程- 02 Workflow 设计模式(上)
前端·网络·人工智能
StarkCoder4 小时前
GetX 状态管理优化:从 GetBuilder 到 Obx 的性能提升实践
前端