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 实现自动按需引入

相关推荐
20261 小时前
14.7 企业级脚手架-制品仓库发布使用
前端·vue.js
用户841794814562 小时前
vue table 甘特图 vxe-gantt 实现多个表格的任务互相拖拽数据
vue.js
程序员张32 小时前
Vue3+ElementPlus—高效存储和回显多选项的状态值
javascript·vue.js·前端框架
白菜豆腐花3 小时前
vue3实现防抖hook
前端·vue.js
秋天的一阵风3 小时前
前端截图方案实战:snapdom 与 html2canvas 的深度对比
前端·javascript·vue.js
前端小巷子4 小时前
watch 与 computed:Vue3响应式的抉择
前端·vue.js·面试
用户6120414922135 小时前
springboot+vue3做的图书管理与借阅系统
vue.js·spring boot·后端
计算机学姐14 小时前
基于SpringBoot的社团管理系统【2026最新】
java·vue.js·spring boot·后端·mysql·spring·mybatis
前端开发爱好者15 小时前
弃用 ESLint + Prettier!快 35 倍的 AI 格式化神器!
前端·javascript·vue.js