Skip to content

Pinia 實戰教學:掌握語法風格與響應式解構技巧

在 Vue 3 的開發世界中,Pinia 提供了極大的靈活性。無論您喜歡傳統的開發模式,還是追求 Composition API 的現代感,Pinia 都能滿足您。本文將帶您深入了解 Pinia 的兩種語法風格,以及在使用時必須注意的「響應式」細節。

Pinia 的兩種語法風格

Pinia 允許開發者根據習慣選擇 Option StoreSetup Store

Option Store (選項式)

與 Vue 2 的架構相似,適合喜歡將資料 state、計算屬性 getters 與方法 actions 清晰拆分的開發者。

js
// stores/counter.js
import { defineStore } from "pinia";

export default defineStore("counter", {
  // 儲存資料處,類似 data
  state: () => {
    return {
      count: 0,
    };
  },
  // 計算衍生狀態,類似 computed
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  // 修改資料的方法,類似 methods
  actions: {
    increment() {
      this.count++;
    },
  },
});

Setup Store (組合式)

這是偏向 Composition API 的寫作方式,傳入一個函式並回傳需要暴露的屬性,結構更彈性。

js
// stores/counter.js
import { ref, computed } from "vue";
import { defineStore } from "pinia";

export default defineStore("counter", () => {
  const count = ref(0); // 相當於 state
  const doubleCount = computed(() => count.value * 2); // 相當於 getters

  function increment() {
    // 相當於 actions
    count.value++;
  }

  return {
    count,
    doubleCount,
    increment,
  };
});

快速對照表

  • ref() / reactive()state
  • computed()getters
  • function()actions

如何在元件中正確使用 Store?

定義完 Store 後,必須在元件中引入並呼叫,才能發揮作用。

vue
// components/Counter.vue
<script setup>
import useCounterStore from "@/stores/counter";

const counterStore = useCounterStore();
</script>

<template>
  <div>
    <p>計數器: {{ counterStore.count }}</p>
    <p>雙倍計數: {{ counterStore.doubleCount }}</p>
    <input @click="counterStore.increment" type="button" value="increment" />
  </div>
</template>

進階:避免解構導致的響應式失效

這是許多 Vue 開發者常遇到的陷阱:store 是一個用 reactive 包裝的物件。如果您直接對它進行解構(Destructuring),解構出來的資料會失去響應式特性,畫面將不會隨資料更新。

錯誤示範(會失去響應式)

js
const { count, doubleCount } = counterStore; // 這樣拿到的只是普通的數值,不會聯動更新

正確做法:使用 storeToRefs()

為取出 store 中的屬性並保持其響應式,我們必須使用 Pinia 提供的 storeToRefs() 工具。若為 action 或非響應式的屬性,直接解構無妨。如下:

vue
// components/Counter.vue
<script setup>
import { storeToRefs } from "pinia";
import useCounterStore from "@/stores/counter";

const counterStore = useCounterStore();
const { count, doubleCount } = storeToRefs(counterStore);
const { increment } = counterStore;
</script>

<template>
  <div>
    <p>計數器: {{ count }}</p>
    <p>雙倍計數: {{ doubleCount }}</p>
    <input @click="increment" type="button" value="increment" />
  </div>
</template>

總結

掌握了 Option / Setup Store 的語法差異以及 storeToRefs 的使用時機,您已經避開了 Pinia 最常見的錯誤。選擇適合專案的寫法,能讓您的 Vue 3 狀態管理既優雅又強大。