前言
在 Vue 3 中,Hook 函数是一种特殊的函数,用于封装可重用的逻辑和状态管理。Hook 函数允许你在 Vue 组件中提取和复用逻辑,而不是将所有逻辑都放在组件的选项对象中。它们可以帮助你更好地组织代码,提高代码的可维护性和可测试性。Hook 函数的特点:
可重用性:Hook 函数可以在多个组件中重复使用,避免了重复编写相同的逻辑。
逻辑封装:将特定的逻辑封装在 Hook 函数中,使组件的代码更加清晰和易于理解。
状态管理:Hook 函数可以用于管理组件的状态,包括响应式数据和副作用。
测试友好:由于 Hook 函数是独立的函数,可以更容易地进行单元测试。
一、Hook 函数的使用方法
创建 Hook 函数,Hook 函数通常是一个普通的 JavaScript 函数,可以接受参数并返回一个对象或函数。例如,以下是一个简单的 Hook 函数,用于管理一个计数器:
import { reactive, toRefs } from 'vue';export function useCounter(initialValue = 0) {const state = reactive({count: initialValue,});const increment = () => {state.count++;};const decrement = () => {state.count--;};return {...toRefs(state),increment,decrement,};}
二、在组件中使用 Hook 函数
在 Vue 组件中,可以通过导入 Hook 函数并调用它来使用其中的逻辑和状态。例如,以下是一个使用
useCounter
Hook 函数的组件:
<template><div><p>Count: {{ count }}</p><button @click="increment">Increment</button><button @click="decrement">Decrement</button></div></template><script>import { useCounter } from './hooks/useCounter';export default {setup() {const { count, increment, decrement } = useCounter();return {count,increment,decrement,};},};
</script>
三、Hook 函数的应用场景
状态管理:Hook 函数可以用于管理组件的状态,例如计数器、表单数据、加载状态等。
副作用管理:可以使用 Hook 函数来管理副作用,如订阅事件、定时器、异步请求等。
逻辑复用:将通用的逻辑封装在 Hook 函数中,以便在多个组件中重复使用,例如数据验证、权限检查等。
四、常见的 HOOK 函数案例
一、数据获取 Hook。假设你经常需要在不同组件中进行数据获取操作,可以创建一个数据获取 Hook。
import { ref, onMounted } from 'vue';export function useDataFetch(apiUrl) {const data = ref(null);const loading = ref(true);const error = ref(null);onMounted(async () => {try {const response = await fetch(apiUrl);if (!response.ok) {throw new Error('Network response was not ok');}data.value = await response.json();} catch (err) {error.value = err;} finally {loading.value = false;}});return { data, loading, error };
}
使用示例:
<template><div v-if="loading">Loading...</div><div v-else-if="error">{{ error.message }}</div><div v-else><!-- 展示获取到的数据 --><p>{{ data.someProperty }}</p></div>
</template><script>
import { useDataFetch } from './yourHooks';export default {setup() {const { data, loading, error } = useDataFetch('https://your-api-url.com/data');return { data, loading, error };},
};
</script>
二、表单验证 Hook。用于处理表单验证逻辑。
import { ref } from 'vue';export function useFormValidation() {const formData = ref({});const errors = ref({});const validate = () => {// 假设这里进行一些简单的验证,比如检查某个字段是否为空if (!formData.value.username) {errors.value.username = 'Username is required';} else {delete errors.value.username;}// 可以根据实际需求扩展更多验证逻辑return Object.keys(errors.value).length === 0;};return { formData, errors, validate };
}
使用示例:
<template><form @submit.prevent="submitForm"><input v-model="formData.username" /><p v-if="errors.username">{{ errors.username }}</p><button>Submit</button></form>
</template><script>
import { useFormValidation } from './yourHooks';export default {setup() {const { formData, errors, validate } = useFormValidation();const submitForm = () => {if (validate()) {// 处理表单提交逻辑}};return { formData, errors, submitForm };},
};
</script>
三、鼠标位置跟踪 Hook。跟踪鼠标在页面上的位置
使用示例:
<template><div>Mouse position: {{ x }}, {{ y }}</div>
</template><script>
import { useMousePosition } from './yourHooks';export default {setup() {const { x, y } = useMousePosition();return { x, y };},
};
</script>
五、Vue3 自定义 Hooks 为什么这么好用?
1、组合式 API 和选项 API
Vue2 提供的编程方式是 Options API,即选项式 API。我们需要在 data 里面定义变量,在 methods 里面定义方法,在 computed 定义计算后的逻辑。
在开发功能的时候,我们需要在 data 、methods、computed 之间来回找代码。如果功能非常复杂, data 、methods、computed 等里面的代码就会非常长,不好维护。
后来 Vue3 出现了,它提供的编程方式是 Composition API,即组合式 API。在开发功能的时候,我们根据逻辑功能去组织代码,一个功能所定义的所有 API 会放在一起。
但是如果业务功能太复杂,script 标签里面的代码也会又臭又长,而且并不是很多人都有加注释的习惯,所以时间长了也不好维护。
那能不能把相同逻辑功能的代码分别放到到不同的文件里,其他地方想用的时候直接导入就可以复用了呢?有的,自定义 Hooks 出现了。
2、自定义 Hooks 介绍
Vue 的自定义 Hooks 是一种封装可重用逻辑的方式。它允许你将复杂的逻辑提取出来,形成独立的函数,然后在不同的组件中复用。这样可以避免在多个组件中重复编写相同的逻辑,提高代码的可读性和可维护性。通俗易懂来说就是:
1.将可复用的功能逻辑放到一个 js 文件里面,并通过 export 导出。
2.定义 Hooks 的时候,js 的文件名和方法名通常以 use 开头,例如 useAddOrder、useChangeData。
3.通过 import 导入相关的 js 文件,引用时通过解构显示相关的变量和方法。
3、自定义 Hooks 案例
3.1 案例1
创建一个简单的计数器 Hooks
使用 Hooks
<template><div><p>count: {{ count }}</p><el-divider></el-divider><el-button type="primary" @click="increment">新增</el-button><el-button type="success" @click="decrement">减少</el-button></div>
</template>
<script setup>
// 导入 hooks
import { useCounter } from "../hooks/useCounter";
// 解构引入
const { count, increment, decrement } = useCounter();
</script>
3.2 案例2
创建一个监听浏览器窗口大小变化的 Hooks
使用 Hooks
<template><div><p>浏览器窗口宽度: {{ width }}</p><p>浏览器窗口高度: {{ height }}</p></div>
</template>
<script setup>
// 导入 hooks
import { useWindowResize } from "../hooks/useWindowResize";
// 解构引入
const { width, height } = useWindowResize();
</script>
4、自定义 Hooks 优势
所谓的自定义 Hooks 就是在开发 Vue3 项目时,我们将 script 里面相同逻辑功能的变量和方法等封装到一个 js 文件里面,然后通过 export导出。然后在任何页面都可以通过导入、解构的方式使用,大大提高代码的复用性。自定义 Hooks 将相同的功能代码从一堆代码中解耦出来,让组件结构更清晰,便于维护。
Hooks 直译是“钩子”,所以又把这些定义的 js 叫做钩子函数。