Vue3 自定义 Hook 实战指南:从原理到开箱即用的 Hook 推荐

在 Vue3 的 Composition API 中,自定义 Hook(Custom Hooks) 是提升代码复用性和可维护性的核心利器。它通过将组件逻辑封装为独立的函数,让开发者能够像"搭积木"一样快速构建复杂功能。本文将深入解析自定义 Hook 的设计原则,并推荐一系列开箱即用的 Vue3 Hook 库,助你高效开发!


一、为什么需要自定义 Hook?

在 Vue2 的 Options API 中,逻辑复用通常依赖 mixins 或高阶组件,但这些方案存在命名冲突隐式依赖来源不清晰 等问题。而 Vue3 的 Composition API 通过纯函数的方式解决了这些问题:

  1. 逻辑解耦:将相关逻辑(如数据获取、事件监听)封装到单个函数中。
  2. 命名清晰 :通过 useXXX 前缀明确标识 Hook,避免混淆。
  3. 灵活组合:像乐高一样拼接多个 Hook,构建复杂功能。

二、自定义 Hook 的核心设计原则

1. 单一职责原则

每个 Hook 应只关注一个功能。例如:

  • useFetch:仅处理数据请求。
  • useUser:同时处理数据请求、表单验证和权限控制。

2. 明确输入输出

通过参数和返回值定义清晰的接口:

javascript 复制代码
// 示例:分页 Hook
interface PaginationConfig {
  url: string;
  pageSize: number;
}

export function usePagination(config: PaginationConfig) {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);

  const fetchPage = async (page: number) => {
    setLoading(true);
    const res = await fetch(`${config.url}?page=${page}`);
    setData(await res.json());
    setLoading(false);
  };

  return { data, loading, fetchPage };
}

3. 副作用管理

在 Hook 中添加事件监听、定时器等副作用时,必须通过 onMountedonUnmounted 清理:

javascript 复制代码
export function useWindowSize() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return width;
}

4. 响应式数据优化

  • 基本类型用 ref,对象/数组用 reactive
  • 避免不必要的响应式转换(如临时变量无需用 ref)。

三、开箱即用的 Vue3 Hook 库推荐

1. VueUse

特点 :Vue 官方推荐的 Hook 库,提供 100+ 常用 Hook,覆盖动画、浏览器、状态管理、传感器等场景。
安装

bash 复制代码
npm install @vueuse/core

常用 Hook 示例

  • useMouse :追踪鼠标位置。

    javascript 复制代码
    import { useMouse } from '@vueuse/core';
    const { x, y } = useMouse();
  • useFetch :简化数据请求。

    javascript 复制代码
    const { data, isLoading } = useFetch('https://api.example.com/data');
  • useDebounceFn :防抖函数。

    javascript 复制代码
    const debouncedSearch = useDebounceFn((query) => {
      console.log('Search:', query);
    }, 500);

2. Composables

特点 :专注于 UI 逻辑的 Hook 集合,如表单验证、拖拽、虚拟滚动等。
安装

bash 复制代码
npm install @composables/core

示例

  • useForm :表单验证。

    javascript 复制代码
    const { errors, validate } = useForm({
      email: { required: true, email: true },
    });

3. Ahooks-vue

特点 :受 React Ahooks 启发,提供状态管理、副作用、生命周期等 Hook。
安装

bash 复制代码
npm install ahooks-vue

示例

  • useInterval :定时器。

    javascript 复制代码
    useInterval(() => {
      console.log('Tick every 1s');
    }, 1000);

4. Vant Use

特点 :Vant UI 团队提供的移动端专用 Hook,如地理定位、设备信息等。
安装

bash 复制代码
npm install vant-use

示例

  • useGeolocation :获取用户位置。

    javascript 复制代码
    const { position, error } = useGeolocation();

四、自定义 Hook 实战案例

案例 1:表格分页 Hook

javascript 复制代码
export function useTablePagination<T>(apiUrl: string) {
  const [data, setData] = useState<T[]>([]);
  const [loading, setLoading] = useState(false);
  const [pagination, setPagination] = useState({
    page: 1,
    pageSize: 10,
    total: 0,
  });

  const fetchData = async () => {
    setLoading(true);
    const res = await fetch(`${apiUrl}?page=${pagination.page}&size=${pagination.pageSize}`);
    const result = await res.json();
    setData(result.list);
    setPagination(prev => ({ ...prev, total: result.total }));
    setLoading(false);
  };

  const handlePageChange = (page: number) => {
    setPagination(prev => ({ ...prev, page }));
  };

  useEffect(() => {
    fetchData();
  }, [pagination.page, pagination.pageSize]);

  return { data, loading, pagination, handlePageChange };
}

案例 2:主题切换 Hook

javascript 复制代码
export function useTheme() {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');

  useEffect(() => {
    document.documentElement.className = theme;
  }, [theme]);

  const toggleTheme = () => {
    setTheme(prev => (prev === 'light' ? 'dark' : 'light'));
  };

  return { theme, toggleTheme };
}

五、总结

  1. 自定义 Hook 是 Vue3 的核心优势,通过函数式编程提升代码复用性。
  2. 遵循设计原则:单一职责、明确接口、副作用管理、响应式优化。
  3. 善用开源库:VueUse、Composables 等库覆盖了大多数场景,避免重复造轮子。
  4. 从简单到复杂:先封装基础 Hook(如数据请求),再逐步构建高级组合。

六、资源推荐

  • 官方文档vueuse.org(按分类浏览所有 Hook)
  • 示例仓库VueUse Playground
  • 进阶技巧 :结合 unplugin-vue-components 实现自动按需引入

相关推荐
Python私教9 小时前
Pure-Admin-Thin 深度解析:完整版和精简版到底怎么选?
vue.js·人工智能·开源
ayqy贾杰11 小时前
Cursor SDK发布!开发者可直接搬走其内核
前端·vue.js·面试
李白的天不白12 小时前
vue 数据格式问题
前端·vue.js·windows
小白蒋博客12 小时前
【ai开发段永平投资理财的知识图谱网站】第一天:搭 Vite + Vue 项目,跑通 Hello World
vue.js·人工智能·trae
@yanyu6661 天前
登录注册功能-明文
vue.js·springboot
滕青山1 天前
在线PDF拆分工具核心JS实现
前端·javascript·vue.js
光影少年1 天前
前端在页面渲染优化和组件优化经验?
前端·vue.js·react.js·前端框架
李白的天不白1 天前
VUE依赖配置问题
前端·javascript·vue.js
小智社群1 天前
获取贝壳新房列表
前端·javascript·vue.js
一 乐1 天前
茶叶商城|基于springboot + vue茶叶商城系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·茶叶商城系统