状態管理
props
と emit
を使った親子間のデータ連携は便利ですが、これだけでは以下のようなケースでは十分ではありません。データの受け渡しが複雑になりがちです。
- コンポーネントの階層が深くなったり、
- 親子関係にないコンポーネント間でデータを共有したい
このような問題を解決するのが、状態管理ライブラリです。
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 を使ってみよう
- インストール:
npm install pinia
- 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')
- 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 } })
- コンポーネントでの使用:
<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 を使うことで、アプリのどんな場所からでも、共有したいデータにアクセスし、統一された方法で変更できるようになります。これにより、大規模なアプリでもデータの流れが明確になり、管理が容易になります。