vue-hooks | 走向react式风格
2025-01-21 09:06 阅读(112)

前言

在Vue3的开发世界中,Hooks是一项极具创新性和实用性的特性,它为开发者带来了全新的编程体验和诸多优势 , 越来越像 react 的风格。

什么是Vue3 Hooks

Vue3 Hooks本质上是基于Vue3的组合式API实现的一组可复用函数。

通过这些函数,开发者可以将组件中的逻辑代码进行抽离和封装,实现代码的复用和更好的组织架构。与Vue2中的混入(Mixin)类似,但Vue3 Hooks更清晰地展示了复用功能代码的来源,避免了Mixin可能出现的命名冲突、难以追踪来源等问题。

Vue3 Hooks的优势


提高代码复用性


将多个组件共享的逻辑封装成一个Hook,然后在需要的组件中导入并使用,避免了重复编写相同代码,提高了代码的复用率。例如,在多个组件中都需要实现获取用户信息的功能,就可以将这个逻辑封装成一个useUserInfo的Hook,在各个组件中直接调用。


增强逻辑清晰度


允许按照功能来组织代码,而不是像传统的Vue组件那样按照生命周期来组织。这样使得组件内部的逻辑更加清晰,易于理解和维护。比如,将与数据获取相关的逻辑放在一个Hook中,与表单验证相关的逻辑放在另一个Hook中,每个Hook都有明确的职责。


简化状态管理


使用reactive和ref等函数可以方便地创建响应式数据,提供了一种声明式的方式来处理数据变化,让状态管理变得更加直观。例如,通过ref创建一个响应式的计数器count,可以直接在模板中使用{{ count }}来显示计数器的值,并且当count的值发生变化时,模板会自动更新。


更好的副作用管理


可以使用onMounted、onUnmounted等生命周期钩子来管理副作用操作,如定时器、事件监听等。确保在组件卸载时正确清理这些副作用,避免内存泄漏等问题。比如,在onMounted钩子中添加一个事件监听,在onUnmounted钩子中移除该事件监听。

Vue3常用的Hooks函数


响应式数据相关


ref用于创建一个响应式的引用,常用于基本数据类型;reactive用于创建一个响应式的对象,常用于复杂数据类型;computed用于基于其他数据计算得出的数据属性,它具有缓存功能,只有在依赖的数据发生变化时才会重新计算。


生命周期相关


onMounted在组件挂载到DOM之后调用,常用于初始化数据、添加事件监听等操作;onBeforeUpdate在组件更新之前调用,可以在这个钩子中进行一些数据的预处理;onUnmounted在组件卸载之后调用,用于清理副作用,如清除定时器、移除事件监听等。


监听数据变化相关


watch和watchEffect用于监听数据变化并执行副作用。watch需要指定监听的数据源,而watchEffect会自动收集依赖的响应式数据,并在其变化时重新执行回调函数。

自定义Hooks

在Vue3中,开发者还可以自定义Hooks来满足特定的业务需求。自定义Hooks应该遵循一定的规范,以确保代码的可读性和可维护性。


命名规范:以“use”为前缀,例如useUserInfo、useMousePosition等。这样可以清晰地表明这是一个自定义的Hook函数。

参数与返回值:接收明确的参数,并返回需要在组件中使用的响应式数据、方法、计算属性等。返回的对象应该具有清晰的属性名和结构。

副作用管理:如果包含副作用操作,应确保在组件卸载时正确清理这些副作用。可以使用onMounted、onUnmounted等生命周期钩子来管理副作用的添加和移除。


我们举一个有副作用(内存泄漏)的代码 , 之后逐步改善为 hooks 风格

<template>
    <div>
        <p>Mouse X:{{ mousePos.x }}</p>
        <p>Mouse Y:{{ mousePos.y }}</p>
    </div>
</template>

<script setup>
import {reactive, onMounted , onUnmounted} from 'vue'
let mousePos = reactive({
    x : 0,
    y : 0
})

const mouseMoveHandler = (e)=>{
        mousePos.x = e.clientX;
        mousePos.y = e.clientY;
        // 内存泄露
        console.log("我还在~");
    }
onMounted(()=>{
    window.addEventListener('mousemove',)
})


</script>

<style scoped>

</style>

在卸载组件之后 , 控制台仍然显示“我还在~” , 监听事件没有卸载掉 ,造成内存泄露

https://www.zuocode.com

于是我们利用 vue3 的生命周期 , 在组件卸载之后 ,清除事件监听

onUnmounted(()=>{
    // 防止内存泄露
    window.removeEventListener('mousemove',mouseMoveHandler)
    console.log("我被移除了~");
})

效果如下 :

卸载组件之后 ,没有鼠标的事件监听就没了 ~

而使用 vue3 hooks 风格将会更加优雅 , 优雅永不过时 ~

我们将还有生命周期 和 响应式代码封装为 useMouse , 作为模块导出 , 从而实现 UI 与 State 分离 , 嚓 , 这是不是很 react , react 框架本身专注于视图 , 也是实现了业务与视图的分离 , 所以很适合大型项目

代码如下 :

<template>
    <div>
        <p>Mouse X:{{ x }}</p>
        <p>Mouse Y:{{ y }}</p>
    </div>
</template>

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

const { x, y } = useMouse()



// let mousePos = reactive({
//     x: 0,
//     y: 0
// })

// const mouseMoveHandler = (e) => {
//     mousePos.x = e.clientX;
//     mousePos.y = e.clientY;
//     // 内存泄露
//     console.log("我还在~");
// }

// onMounted(() => {
//     window.addEventListener('mousemove',mouseMoveHandler)
// })


</script>

<style scoped></style>
import { ref, onMounted, onUnmounted } from 'vue';
// export 关键字就是模块化输出
export function useMouse() {
    const x = ref(0);
    const y = ref(0);

    function update(event) {
        x.value = event.pageX;
        y.value = event.pageY;
    }

    onMounted(() => {
        window.addEventListener('mousemove', update);
        console.log('我还在~');
    });

    onUnmounted(() => {
        window.removeEventListener('mousemove', update);
        console.log('我被移除了~');
    });

    return { x, y };
}

场景

在实际项目中,Vue3 Hooks可以广泛应用于各种场景。

比如,在一个电商项目中,可以创建一个useCart的Hook来管理购物车的逻辑,包括添加商品、删除商品、计算总价等功能;

还可以创建一个useSearch的Hook来处理搜索功能,包括发送搜索请求、显示搜索结果等。通过使用自定义Hooks,将这些复杂的逻辑封装起来,使得组件的代码更加简洁和易于维护。

Vue3 Hooks是Vue3开发中的一项重要特性,提供了一种更加灵活、高效的方式来组织和复用代码。

通过合理地使用Vue3 Hooks,可以提高代码的质量和开发效率,让Vue3项目的开发更加轻松和愉快


作者:浪遏

链接:https://juejin.cn