Vue 3 提供的 hook(組合式函數) 和普通函數在使用場景、功能和設計目的上有明顯區別,它們是 Vue 3 組合式 API 的核心概念。下面從幾個關鍵維度分析它們的差異:
1. 設計目的不同
-
Hook(組合式函數)
- 專為 Vue 組件設計,用于封裝和復用有狀態的邏輯(如響應式數據、生命周期鉤子、DOM 操作等)。
- 可以在組件間共享邏輯,同時保持響應式特性和生命周期的關聯。
- 例如:
useState
、useEffect
、useRouter
等。
-
普通函數
- 通用工具函數,不依賴 Vue 的響應式系統或生命周期,用于執行無狀態的計算或操作。
- 例如:格式化日期、計算數學表達式、處理數組等。
2. 響應式能力不同
-
Hook
- 可以創建和管理 響應式數據(如
ref
、reactive
),并在數據變化時觸發組件更新。 - 示例:
import { ref, onMounted } from 'vue';function useCounter() {const count = ref(0);const increment = () => count.value++;onMounted(() => {console.log('計數器已掛載');});return { count, increment }; }
- 可以創建和管理 響應式數據(如
-
普通函數
- 無法直接創建響應式數據,返回的結果通常是靜態值或普通對象。
- 示例:
function formatCurrency(amount) {return `¥${amount.toFixed(2)}`; }
3. 生命周期關聯不同
-
Hook
- 可以使用 Vue 的 生命周期鉤子(如
onMounted
、onUnmounted
),在特定階段執行副作用。 - 示例:在組件掛載時自動獲取數據。
- 可以使用 Vue 的 生命周期鉤子(如
-
普通函數
- 沒有生命周期概念,無法感知組件的掛載、更新或卸載。
4. 調用時機限制不同
-
Hook
- 必須在 組件的
setup()
函數或其他 Hook 內部調用,且不能在條件語句、循環或嵌套函數中調用(需遵循 Hook 調用規則)。 - 這是為了確保 Vue 能正確追蹤依賴關系。
- 必須在 組件的
-
普通函數
- 可以在任何地方調用,沒有特殊限制。
5. 狀態管理方式不同
-
Hook
- 可以封裝和管理組件的 內部狀態,并通過返回值暴露給組件使用。
- 示例:
function useMousePosition() {const x = ref(0);const y = ref(0);const updatePosition = (e) => {x.value = e.pageX;y.value = e.pageY;};onMounted(() => window.addEventListener('mousemove', updatePosition));onUnmounted(() => window.removeEventListener('mousemove', updatePosition));return { x, y }; }
-
普通函數
- 不管理狀態,僅提供計算或操作能力。
6. 依賴注入方式不同
-
Hook
- 可以通過
inject
獲取 依賴注入(如provide
提供的上下文)。
- 可以通過
-
普通函數
- 通常需要通過參數顯式傳遞依賴。
何時使用 Hook 或普通函數?
-
使用 Hook:
- 需要封裝響應式數據、生命周期邏輯或 DOM 操作。
- 需要在多個組件間復用有狀態的邏輯。
- 需要訪問 Vue 的 API(如
watch
、computed
)。
-
使用普通函數:
- 執行純計算或無狀態操作(如工具函數)。
- 不依賴 Vue 的響應式系統或生命周期。
總結
Hook 是 Vue 3 組合式 API 的核心,通過 組合多個有狀態的邏輯 來替代 Vue 2 的選項式 API(data
、methods
、watch
等),使代碼更模塊化、可復用。而普通函數則作為輔助工具,處理無狀態的通用邏輯。兩者結合使用,可以構建更清晰、更易于維護的 Vue 應用。