前言

博主没用过hooks,突然看大项目的时候,看到有个hooks文件夹,好奇什么是hooks,什么时候会用hooks,于是乎就有这篇文章了。

一、为什么需要 Hook?

在 Vue3 中,Hook(钩子) 是基于 Composition API(组合式 API)封装的可复用逻辑函数,本质是将组件中分散的业务逻辑(如数据请求、表单验证、事件监听等)抽离成独立函数,实现逻辑复用和代码组织优化。

1.解决代码复用问题

Vue2 中通过 mixin 复用逻辑,但存在命名冲突、来源不清晰等问题;Hook 基于函数封装,逻辑独立且调用关系明确。

2.优化代码组织

将组件中相关的逻辑(如“分页加载”的请求、页码控制、加载状态)聚合到一个 Hook 中,避免代码碎片化。

3.增强类型支持:

结合 TypeScript 时,Hook 的类型推导更清晰,比 mixin 更易维护。

二、Hook 的核心特点

1.函数形式

通常以 useXxx 命名(如 usePaginationuseForm),符合 React/Vue 社区的命名规范。

2. 依赖 Composition API

内部使用 refreactivewatchonMounted 等 Vue3 API。

3. 可组合性

Hook 之间可以相互调用,实现复杂逻辑的拆分与组合。

三、项目中如何使用 Hook

以下通过 1个实际场景(表单验证)演示 Hook 的定义与使用。
(其实像之前写的 分享页面的方法,就可以单独抽离成一个hooks)

封装表单的“数据绑定、验证逻辑、提交状态”等通用逻辑。

1. 定义 Hook(src/hooks/useForm.ts
import { ref, reactive, computed } from 'vue';

// 定义验证规则类型
type Rule = (value: any) => boolean | string; // 返回 true 表示验证通过,否则返回错误信息
type Rules<T> = { [K in keyof T]?: Rule | Rule[] }; // 每个字段的验证规则

export function useForm<T extends object>(
  initialValues: T, // 表单初始值
  rules: Rules<T> // 验证规则
) {
  // 表单数据
  const formData = reactive<T>({ ...initialValues });
  // 错误信息
  const errors = reactive<Partial<Record<keyof T, string>>>({});
  // 提交状态
  const submitting = ref(false);

  // 单个字段验证
  const validateField = (field: keyof T) => {
    const value = formData[field];
    const ruleList = Array.isArray(rules[field]) ? rules[field] : [rules[field]];

    for (const rule of ruleList) {
      if (!rule) continue;
      const result = rule(value);
      if (result !== true) {
        errors[field] = result as string;
        return false; // 验证失败
      }
    }
    errors[field] = '';
    return true; // 验证通过
  };

  // 整体表单验证
  const validate = (): boolean => {
    let isValid = true;
    Object.keys(rules).forEach((field) => {
      const result = validateField(field as keyof T);
      if (!result) isValid = false;
    });
    return isValid;
  };

  // 提交表单
  const submit = async (onSubmit: (data: T) => Promise<void>) => {
    if (!validate()) return; // 验证失败则不提交
    submitting.value = true;
    try {
      await onSubmit({ ...formData }); // 调用外部传入的提交逻辑
    } finally {
      submitting.value = false;
    }
  };

  // 重置表单
  const reset = () => {
    Object.assign(formData, initialValues);
    Object.keys(errors).forEach((field) => {
      errors[field as keyof T] = '';
    });
  };

  return {
    formData,
    errors,
    submitting,
    validateField,
    validate,
    submit,
    reset
  };
}
2. 在组件中使用 Hook(src/views/LoginForm.vue
<template>
  <form class="login-form">
    <!-- 用户名输入 -->
    <div class="form-item">
      <label>用户名</label>
      <input
        v-model="formData.username"
        @blur="validateField('username')"
        placeholder="请输入用户名"
      />
      <span class="error">{{ errors.username }}</span>
    </div>

    <!-- 密码输入 -->
    <div class="form-item">
      <label>密码</label>
      <input
        type="password"
        v-model="formData.password"
        @blur="validateField('password')"
        placeholder="请输入密码"
      />
      <span class="error">{{ errors.password }}</span>
    </div>

    <!-- 提交按钮 -->
    <button 
      type="button" 
      @click="handleSubmit"
      :disabled="submitting"
    >
      {{ submitting ? '提交中...' : '登录' }}
    </button>
  </form>
</template>

<script setup lang="ts">
import { useForm } from '@/hooks/useForm';
import { loginApi } from '@/api/user'; // 假设的登录接口

// 调用表单 Hook
const {
  formData,
  errors,
  submitting,
  validateField,
  submit
} = useForm(
  // 初始值
  { username: '', password: '' },
  // 验证规则
  {
    username: [
      (val) => val.trim() !== '' || '用户名不能为空',
      (val) => val.length >= 3 || '用户名至少3个字符'
    ],
    password: (val) => val.length >= 6 || '密码至少6个字符'
  }
);

// 处理提交
const handleSubmit = () => {
  submit(async (data) => {
    // 调用登录接口
    await loginApi(data);
    alert('登录成功');
  });
};
</script>

四、hooks参考

文档:快速通道

在这里插入图片描述
在这里插入图片描述
(以上的示例函数可以参考)

总结

  1. Hook 的本质:用函数封装可复用逻辑,依赖 Vue3 的 Composition API。
  2. 使用步骤
  • 定义:创建 useXxx.ts 文件,内部实现逻辑并返回需要暴露的状态和方法。
  • 调用:在组件中导入 Hook 并执行,解构出需要的状态和方法,直接在模板或逻辑中使用。
  1. 优势:逻辑复用更清晰、代码组织更有序、类型支持更友好,是 Vue3 项目中推荐的逻辑复用方案。

通过 Hook,可将项目中重复出现的逻辑(如分页、表单、权限、订阅等)抽离,大幅提升代码复用率和可维护性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐