目的:将公共逻辑提取出来,类似于 mixin,解决了mixin的设计缺陷。
React 和 Vue 自定义 Hooks 实现对比
React 自定义 Hooks
React 的自定义 Hooks 是 JavaScript 函数,它们以 use
开头,可以调用其他 Hooks。
基本规则
- 必须以
use
开头命名 - 可以在内部调用其他 Hooks
- 只能在 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 的功能,但实现方式不同。
基本规则
- 使用
ref
或reactive
创建响应式数据 - 使用
computed
创建计算属性 - 使用
watch
或watchEffect
监听变化 - 将逻辑组织在
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>
关键区别
响应式系统:
- React: 依赖状态更新触发重新渲染
- Vue: 基于 Proxy 的自动响应式系统
依赖管理:
- React Hooks 需要手动声明依赖数组
- Vue 自动跟踪依赖关系
生命周期:
- React: 使用 useEffect 模拟生命周期
- Vue: 提供明确的生命周期钩子函数
语法:
- React: 必须在函数组件顶层调用 Hooks
- Vue: 可以在
<script setup>
中自由组织代码
两种框架的自定义 Hook/组合函数都旨在提高代码的可复用性和组织性,但实现方式和理念有所不同。