React 和 Vue的自定义Hooks是如何实现的,如何创建自定义钩子

发布于:2025-07-16 ⋅ 阅读:(17) ⋅ 点赞:(0)

目的:将公共逻辑提取出来,类似于 mixin,解决了mixin的设计缺陷。

React 和 Vue 自定义 Hooks 实现对比

React 自定义 Hooks

React 的自定义 Hooks 是 JavaScript 函数,它们以 use 开头,可以调用其他 Hooks。

基本规则

  1. 必须以 use 开头命名
  2. 可以在内部调用其他 Hooks
  3. 只能在 React 函数组件或其他 Hooks 中调用

示例:自定义计数器 Hook

import { useState } from 'react';

// 自定义计数器 Hook
function useCounter(initialValue = 0, step = 1) {
  const [count, setCount] = useState(initialValue);
  
  const increment = () => setCount(prev => prev + step);
  const decrement = () => setCount(prev => prev - step);
  const reset = () => setCount(initialValue);
  
  return { count, increment, decrement, reset };
}

// 使用自定义 Hook
function CounterComponent() {
  const { count, increment, decrement, reset } = useCounter(0, 2);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

示例:自定义数据获取 Hook

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        if (!response.ok) throw new Error('Network response was not ok');
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// 使用示例
function UserList() {
  const { data, loading, error } = useFetch('https://api.example.com/users');
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  return (
    <ul>
      {data.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Vue 3 组合式 API (类似 Hooks 的概念)

Vue 3 的组合式 API 提供了类似 React Hooks 的功能,但实现方式不同。

基本规则

  1. 使用 refreactive 创建响应式数据
  2. 使用 computed 创建计算属性
  3. 使用 watchwatchEffect 监听变化
  4. 将逻辑组织在 setup 函数或 <script setup>

示例:自定义计数器 Hook

<script setup>
import { ref } from 'vue';

// 自定义计数器组合函数
function useCounter(initialValue = 0, step = 1) {
  const count = ref(initialValue);
  
  const increment = () => count.value += step;
  const decrement = () => count.value -= step;
  const reset = () => count.value = initialValue;
  
  return { count, increment, decrement, reset };
}

// 使用自定义组合函数
const { count, increment, decrement, reset } = useCounter(0, 2);
</script>

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="reset">Reset</button>
  </div>
</template>

示例:自定义数据获取 Hook

<script setup>
import { ref, onMounted } from 'vue';

function useFetch(url) {
  const data = ref(null);
  const loading = ref(true);
  const error = ref(null);

  const fetchData = async () => {
    try {
      const response = await fetch(url);
      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;
    }
  };

  onMounted(fetchData);

  return { data, loading, error };
}

// 使用示例
const { data, loading, error } = useFetch('https://api.example.com/users');
</script>

<template>
  <div v-if="loading">Loading...</div>
  <div v-else-if="error">Error: {{ error.message }}</div>
  <ul v-else>
    <li v-for="user in data" :key="user.id">{{ user.name }}</li>
  </ul>
</template>

关键区别

  1. 响应式系统:

    • React: 依赖状态更新触发重新渲染
    • Vue: 基于 Proxy 的自动响应式系统
  2. 依赖管理:

    • React Hooks 需要手动声明依赖数组
    • Vue 自动跟踪依赖关系
  3. 生命周期:

    • React: 使用 useEffect 模拟生命周期
    • Vue: 提供明确的生命周期钩子函数
  4. 语法:

    • React: 必须在函数组件顶层调用 Hooks
    • Vue: 可以在 <script setup> 中自由组织代码

两种框架的自定义 Hook/组合函数都旨在提高代码的可复用性和组织性,但实现方式和理念有所不同。


网站公告

今日签到

点亮在社区的每一天
去签到