Vue の状態管理


状態管理

propsemit を使った親子間のデータ連携は便利ですが、これだけでは以下のようなケースでは十分ではありません。データの受け渡しが複雑になりがちです。

  • コンポーネントの階層が深くなったり、
  • 親子関係にないコンポーネント間でデータを共有したい

このような問題を解決するのが、状態管理ライブラリです。

Pinia ストア

Vue 公式推奨の状態管理ライブラリが Pinia (ピニア) です。Pinia は、アプリ全体のデータを一元的に管理し、どのコンポーネントからでもデータにアクセスしたり、更新したりできるようにします。

+-----------------------+
|      Pinia Store      |
|  (アプリ全体の状態)   |
+-----------+-----------+
            ^
            |
            | データの参照
            | データの更新
            |
            v
+-------------------------------------+
|        任意のコンポーネント         |
|   (ComponentA, ComponentB, ...)     |
+-------------------------------------+

Pinia Store (ストア) は、共有したいデータ (状態) と、それを操作するための関数 (アクション) をまとめて定義する場所です。アプリに 1 つまたは複数のストアを持つことができます。

Pinia ストアの主な要素

要素 説明
State 共有するデータ本体 count: 0, userList: []
Getters State から派生した計算値を取得 (キャッシュされる) doubleCount, activeUsers
Actions データの変更処理 (関数) increment(), fetchUsers()

詳細

  • State (ステート): ストアに保存されている「データ本体」です。これはリアクティブであり、変更されるとそれを使用しているすべてのコンポーネントに自動で反映されます。
  • Getters (ゲッター): ステートから派生した (加工された) 値を計算し、取得するための関数です。computed プロパティのように、依存するデータが変更されたときだけ再計算され、キャッシュされます。
  • Actions (アクション): ステートを変更するための関数です。データの変更ロジックや、非同期処理 (API 通信 等) をここに記述します。

Pinia を使ってみよう

  1. インストール:
    npm install pinia
    
  2. Pinia の初期設定 (main.js など):
    // main.js
    import { createApp } from 'vue'
    // Pinia をインポート
    import { createPinia } from 'pinia'
    import App from './App.vue'
    
    const app = createApp(App)
    // アプリに Pinia を適用
    app.use(createPinia())
    app.mount('#app')
    
  3. Store の定義 (stores/counter.js の例):
    // stores/counter.js
    import { defineStore } from 'pinia'
    import { ref, computed } = 'vue'
    
    export const useCounterStore = defineStore('counter', () => {
      // ステート
      const count = ref(0)
    
      // ゲッター
      const doubleCount = computed(() => count.value * 2)
    
      // アクション
      function increment() {
        count.value++
      }
    
      function decrement() {
        count.value--
      }
    
      // 公開
      return { count, doubleCount, increment, decrement }
    })
    
  4. コンポーネントでの使用:
    <template>
      <p>現在のカウント: {{ counterStore.count }}</p>
      <p>ダブルカウント: {{ counterStore.doubleCount }}</p>
      <button @click="counterStore.increment()">増やす</button>
      <button @click="counterStore.decrement()">減らす</button>
    </template>
    
    <script setup>
    // 定義したストアをインポート
    import { useCounterStore } from '../stores/counter'
    
    // ストアを利用可能にする
    const counterStore = useCounterStore()
    </script>
    

Pinia を使うことで、アプリのどんな場所からでも、共有したいデータにアクセスし、統一された方法で変更できるようになります。これにより、大規模なアプリでもデータの流れが明確になり、管理が容易になります。


Comments or feedbacks are welcomed and appreciated.