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

相关推荐
掘金安东尼7 分钟前
上周前端发生哪些新鲜事儿? #407
前端·面试·github
小谭鸡米花16 分钟前
ECharts各类炫酷图表/3D柱形图
前端·javascript·echarts·大屏端
郝晨妤21 分钟前
【鸿蒙5.0】向用户申请麦克风授权
linux·服务器·前端·华为·harmonyos·鸿蒙
神秘代码行者32 分钟前
使用 contenteditable 属性实现网页内容可编辑化
前端·html5
小鱼人爱编程33 分钟前
Look My Eyes 最新IDEA快速搭建Java Web工程的两种方式
java·前端·后端
郝晨妤34 分钟前
【鸿蒙5.0】鸿蒙登录界面 web嵌入(隐私页面加载)
前端·华为·harmonyos
小鱼人爱编程39 分钟前
当上小组长的第3天,我裁掉了2年老员工
前端·后端·面试
晓得迷路了40 分钟前
栗子前端技术周刊第 74 期 - 2025 Vue.js 现状报告、Element Plus X、Material UI v7...
前端·javascript·vue.js
知识分享小能手44 分钟前
CSS3学习教程,从入门到精通, CSS3 变形效果(2D 和 3D)的详细语法知识点及案例代码(22)
前端·javascript·css·学习·3d·css3·html5
花之亡灵1 小时前
.net 6 + vue3中使用SignaIR实现双向通信功能
前端·javascript·笔记·websocket·.net·信息与通信