Vue3 Hooks 入门与实战:打造高效、可复用的逻辑模块 🎣🚀

引言

在Vue3中,hooks并不是官方定义的术语,而是开发者对 Composition API 的编程风格的俗称,在React的hooks为函数组件引入了状态和其他React特性,而Vue3就是借鉴了这种思想从而推出的 Composition API。

何为 Hooks

hooks直译为 钩子 ,理所当然Hook function也被称为 钩子函数。可以将hooks当作鱼钩,将鱼钩抛入水中,在鱼上钩时会返还一个信号给我们,让我们知道鱼上钩了,而hooks在Vue中的作用也差不多,它在代码中会在特定的时机"钩住"一些东西--例如组件的生命周期、状态变化等,并且返还一个信号给我们,这样就可以对这些情况做出反应。

例如:

  • 生命周期钩子:当组件挂载(onMounted)或卸载(onUnmounted)时,"钩子"就会触发,这时我们就可以执行相应的逻辑。
  • 状态变化钩子:通过 watchwatchEffect,我们可以"钩住"某个响应式数据的变化,并在数据更新时执行副作用操作。

何为副作用?

"副作用"指与组件渲染无关的操作,比如:

  • 定时器
  • 事件监听
  • 直接操作 DOM 元素

这些操作会影响组件之外的状态或行为,所以需要管理它们的生命周期,以防内存泄露意外行为

当然其特性不止于此:

  • 拆分逻辑:将组件中复杂的业务逻辑抽离成多个独立的函数,每个函数负责处理一部分逻辑。
  • 复用逻辑:多个组件可以共享拆分出的函数,当然前提是它们的需要这个业务逻辑。

普通封装函数 vs Hook函数

普通封装的工具函数通常不依赖任何的特定状态或上下文环境,并且不会直接与视图层发生交互(不会自动触发视图更新),例如普通的计算函数:

js 复制代码
function add(a, b){
    return a + b;
}

而Hook函数通常包含响应式变量(如refreactive创建的变量),并且能够监听这些变量的变化来触发视图更新。

js 复制代码
import { ref } from 'vue';

// Hook函数
function useCounter(initialValue = 0) {
    const count = ref(initialValue); // 响应式变量 
    
    const increment = () => ++count.value; 
    const decrement = () => --count.value; 
    
    return { count, increment, decrement }; 
}

所以,如何判断一个函数为Hook函数,那么就看其内部是否包含响应式数据。

Hooks 的基本使用

1.命名规范

自定义的 hook函数有一个默认的规矩,那就是命名通常用use开头,例如:useMouse等。(帮助区分普通函数和hook函数)

2.避免直接操作 DOM

直接操作 DOM(如使用 document.getElementById)会破坏 hook函数 声明式的设计,可能导致与 Vue 的响应式系统冲突,如果需要访问请通过refonMounted

3.确保清理副作用

如果 hook函数 中涉及副作用,必须在组件卸载时清理这些副作用,否则可能引发内存泄漏或逻辑错误。

4.避免过度抽象

虽然 hooks 提供了很好的复用性,但不要为了复用而过度抽象。将 hook函数 的职责单一化,专注于解决一个具体的问题。


创建自定义的 Hook

这里我用一个简单的追踪鼠标位置,并且包含开关显示位置的按钮的样例来做演示

js 复制代码
// useMouse.js(建议用单独用一个hooks文件夹存放 hook函数)
import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
    let x = ref(0),
    y = ref(0);

    const mousePosHandler = (e) => {
        x.value = e.pageX
        y.value = e.pageY
        console.log('我还在移动')
    }
    
// -----------------管理副作用----------------------------------
    // 注册事件监听器
    onMounted(() => {
        window.addEventListener('mousemove', mousePosHandler)
    })
    // 移除事件监听器
    onUnmounted(() => {
        window.removeEventListener('mousemove', mousePosHandler) 
    })

    return { x, y }
}

export function useMemo() {
    console.log('userMemo')
}

使用样例

调用 hook 函数并解构返回即可

html 复制代码
<!-- MousePos.vue -->
<template>
    <div>
        <p>Mouse X: {{ x }}</p>
        <p>Mouse Y: {{ y }}</p>
    </div>
</template>

<script setup>
import { useMouse, useMemo } from '../hooks/useMouse'

const { x , y } = useMouse()
useMemo()
</script>

<style scoped>
</style>
html 复制代码
<!-- App.vue -->
<script setup>
import { 
  ref
} from 'vue'

import MousePos from './components/MousePos.vue'

const showMouse = ref(true);
const toggleMouse = () => {
  showMouse.value = !showMouse.value;
}
</script>

<template>
  <div>
    <MousePos v-if="showMouse"/>
    <button @click="toggleMouse">切换显示</button>
  </div>
</template>

<style scoped>
</style>

最终效果

官方文档:VueHook Plus

相关推荐
JC_You_Know39 分钟前
多语言网站的 UX 陷阱与国际化实践陷阱清单
前端·ux
Python智慧行囊1 小时前
前端三大件---CSS
前端·css
Jinuss1 小时前
源码分析之Leaflet中Marker
前端·leaflet
成都渲染101云渲染66661 小时前
blender云渲染指南2025版
前端·javascript·网络·blender·maya
聆听+自律1 小时前
css实现渐变色圆角边框,背景色自定义
前端·javascript·css
牛马程序小猿猴2 小时前
17.thinkphp的分页功能
前端·数据库
huohuopro3 小时前
Vue3快速入门/Vue3基础速通
前端·javascript·vue.js·前端框架
草巾冒小子3 小时前
vue3中解决 return‘ inside ‘finally‘ block报错的问题
前端·javascript·vue.js
互联网搬砖老肖3 小时前
Web 架构之高可用基础
前端·架构
zfyljx3 小时前
五子棋html
前端·css·html