React 和 Vue的自定义Hooks是如何实现的,如何创建自定义钩子
目的:将公共逻辑提取出来,类似于 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/组合函数都旨在提高代码的可复用性和组织性,但实现方式和理念有所不同。