Skip to content

Vue 3 實戰筆記:打造您的第一個 useCounter Composable

在 Vue 專案中,「計數器」功能雖然簡單,卻是理解 Composable (組合式函數) 最好的切入點。透過將計數邏輯從 UI 中抽離,我們能讓元件變得更純粹,並實現邏輯的跨元件共享。

為什麼需要抽離邏輯?

在傳統的單一檔案元件 (SFC) 中,我們常會這樣寫:

vue
// App.vue
<script setup>
import { ref } from "vue";

const count = ref(0);

function increment() {
  count.value++;
}

function decrement() {
  count.value--;
}

function reset() {
  count.value = 0;
}
</script>

<template>
  <p>{{ count }}</p>
  <input @click="increment" type="button" value="increment" />
  <input @click="decrement" type="button" value="decrement" />
  <input @click="reset" type="button" value="reset" />
</template>

這段程式碼在單一頁面運作良好,但如果需要在「購物車數量」、「分頁控制器」或「點擊計數器」中重複這些邏輯,重複撰寫相同的 ref 與函數就會顯得冗餘。

定義 useCounter Composable

遵循 Vue 3 的開發規範,我們在 composables 目錄下建立一個 use 開頭的檔案。我們不只是移動程式碼,而是將其封裝成一個具備單一職責的黑盒子。

實作 useCounter.js

js
// composables/useCounter.js
import { ref } from "vue";

export default () => {
  const count = ref(0);

  function increment() {
    count.value++;
  }

  function decrement() {
    count.value--;
  }

  function reset() {
    count.value = 0;
  }

  return { count, increment, decrement, reset };
};

在元件中輕量化引用

重構後,原本臃腫的元件程式碼縮減為簡單的呼叫。這就是 Composable 的魅力:UI 歸 UI,邏輯歸邏輯。

vue
// App.vue
<script setup>
import useCounter from "@/composables/useCounter";

const { count, increment, decrement, reset } = useCounter();
</script>

<template>
  <p>{{ count }}</p>
  <input @click="increment" type="button" value="increment" />
  <input @click="decrement" type="button" value="decrement" />
  <input @click="reset" type="button" value="reset" />
</template>

深度解析:Composable 的優勢

高度的邏輯複用性

useCounter 不再侷限於特定的元件。任何需要計數功能的頁面,只需要一行 import 即可立即獲得完整的狀態管理。

獨立的響應式狀態

這點至關重要: 每當您在一個新元件中呼叫 useCounter(),Vue 都會建立一個全新的 count 實例。這意味著元件 A 與元件 B 的數值是獨立運作的,互不干擾。

符合單一職責原則 (SRP)

元件現在只負責「顯示數據」與「觸發事件」,而複雜的運算與邏輯變更全部由 Composable 處理。