总结 React Hooks 并对比在 Vue 3 中是怎么使用的

98 阅读2分钟

大家好,我是格子,今天我们来总结一下 React 与 Vue3 的 Hooks,方便我们记忆。

1. useState

作用:管理组件状态 参数initialState(初始状态)
返回值[state, setState](当前状态和更新函数)

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

Vue3 对应ref 或 reactive,相当于就是定义响应式数据

<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
  <button @click="count++">{{ count }}</button>
</template>

差异:Vue 的响应式是自动根据定义的对象变化更新 DOM,但是 React 需手动调用 setState(显式调用,从而更新 DOM)。

2. useEffect

作用:处理副作用(如 API 请求、DOM 操作)
参数(effect, dependencies?)(副作用函数和依赖数组)

useEffect(() => {
  document.title = `Count: ${count}`;
}, [count]); // 仅在 count 变化时执行


// vue onBeforeUnmount、onMounted
useEffect(() => {
  // 类似 vue onMounted
  const timer = setInterval(() => {
    console.log("Running...");
  }, 1000);

  // 类似 vue onBeforeUnmount
  return () => {
    clearInterval(timer); // 清理定时器
  };
}, [dependencies]);

Vue3 对应watchEffect 或 watchuseEffect 返回一个函数时, 则相当于 vueonBeforeUnmount 组件卸载回调,并且 useEffect 首次执行时,相当于 onMounted 方法。

<script setup>
import { watchEffect } from 'vue';
watchEffect(() => {
  document.title = `Count: ${count.value}`;
});
</script>

差异:Vue 自动收集依赖,React 需显式声明依赖数组。

3. useReducer

作用:复杂状态逻辑管理
参数(reducer, initialState, init?)

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment': return state + 1;
    default: return state;
  }
};
const [state, dispatch] = useReducer(reducer, 0);

Vue3 对应reactive + 自定义函数 或 Pinia

<script setup>
import { reactive } from 'vue';
const state = reactive({ count: 0 });
const dispatch = (type) => {
  if (type === 'increment') state.count++;
};
</script>

差异:Vue 更推荐组合式函数或 Pinia 管理复杂状态。

4. useMemo

作用:缓存计算结果
参数(compute, dependencies)

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Vue3 对应computed

<script setup>
import { computed } from 'vue';
const memoizedValue = computed(() => a.value + b.value);
</script>

差异:Vue 的 computed 自动追踪依赖,React 需手动声明。

5. useCallback

作用:缓存函数引用
参数(callback, dependencies)

const memoizedCallback = useCallback(() => doSomething(a), [a]);

Vue3 对应:直接使用函数 或 computed

<script setup>
const memoizedCallback = () => doSomething(a.value); // Vue 自动优化
</script>

差异:Vue 无需显式缓存函数,依赖响应式系统自动处理。

6. useContext

作用:跨组件传递数据
参数Context 对象

const ThemeContext = createContext('light');
const theme = useContext(ThemeContext);

Vue3 对应provide/inject

<!-- Parent -->
<script setup>
import { provide } from 'vue';
provide('theme', 'light');
</script>

<!-- Child -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
</script>

差异:React 需显式 useContext,Vue 通过 inject 直接获取。

7. useRef

作用:保存可变值或 DOM 引用
参数initialValue

const inputRef = useRef(null);
<input ref={inputRef} />

Vue3 对应ref

<script setup>
import { ref } from 'vue';
const inputRef = ref(null);
</script>
<template>
  <input ref="inputRef" />
</template>

差异:Vue 的 ref 通过 .value 访问,React 通过 .current

8. useLayoutEffect

作用:与 useEffect 类似,但同步执行(在 DOM 更新后、浏览器绘制前)

useLayoutEffect(() => {
  // 操作 DOM 元素
}, [deps]);

Vue3 对应:无直接等价,可通过 nextTick 模拟

<script setup>
import { nextTick } from 'vue';
nextTick(() => {
  // DOM 更新后执行
});
</script>

9. useImperativeHandle

作用:自定义暴露给父组件的 ref 方法
参数(ref, createHandle, dependencies?)

const MyInput = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus()
  }));
  return <input ref={inputRef} />;
});

Vue3 对应defineExpose

<!-- Child -->
<script setup>
defineExpose({ focus: () => inputRef.value.focus() });
</script>

差异:Vue 通过 defineExpose 直接暴露属性。

总结对比

React HookVue3 对应核心差异
useStateref/reactiveVue 自动追踪依赖
useEffectwatchEffect/watchVue 自动收集依赖
useReducer组合式函数/PiniaVue 推荐模块化状态管理
useMemo/useCallbackcomputedVue 自动缓存
useContextprovide/inject语法差异,功能相似
useRefref访问方式不同(.current vs .value
useLayoutEffectnextTickVue 无直接等价 API
useImperativeHandledefineExposeVue 更简洁的暴露方式

React Hooks 强调显式声明依赖,Vue Composition API 依赖自动追踪,语法更简洁。