編集中、見た目の確認のために公開
概要
piniaはデータの変更、加工処理など管理を行う。
piniaの設定
viteでvueをinitする際にpiniaをyesとすれば、stores
ディレクトリが生成されcounte.ts
が作成される。
後述に説明するが、piniaはimportして使用するため、ディレクトリやファイル名は気する必要はないが、ここでは初期設定のまま解説する。
また、この際にmain.ts
にapp.use(createPinia())
が追記されるが、counter.tsを使用しているページは作成されないため独自に実装する。
src
...
├─ stores
├─ coutets.ts
...
pinia初期ファイルの中身
初期ファイルであるstore/counter.ts
の中身について解説する。
まず、piniaはdefineStore()
関数をインポートしてその実行結果をuseCounterStoreとしてエクスポートしている。
これを各コンポーネントでインポートすることにより、counter.tsで作成した変数や関数を使用する。
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
defineStore()関数
piniaのキーとなるdefineStore()
関数について。
引数
defineStore()
は以下の2つの引数を受け取る。
・id
・options
引数 | 内容 |
id | ストアを識別するための一意な名前。 (ストアのファイル名と同じにするとわかりやすい) |
options | ストアを定義するためのオプション。 Optionsオブジェクトまたは Setup関数のいずれかを受け取る。 |
id(第一引数)
ストアは複数定義できるため第1引数にはストアを識別するための一意な名前(id)を指定する。
任意の名前を付けられるが、ストアのファイル名と同じにすると関係がわかりやすい。
options(第二引数)
optionsには以下のいずれかを受け取ってストアを定義することができる。
・Optionsオブジェクト(Option Stores)
・Setup関数(リアクティブなオブジェクトを返す関数)(Setup Stores)
初期サンプルではref()で値を操作したSetup関数を引数としている。
optionsオブジェクト
初期サンプルの内容をoptionsオブジェクトで記述した内容を下記する。
state
プロパティは、オブジェクトを戻り値とするアロー式を記述する。
getter
プロパティは、オブジェクトを記述する。
この際、オブジェクトのプロパティ名がgetter名となる。
actions
プロパティでは、オブジェクトに関数を記述する。
optionsオブジェクト | 内容 |
state | データ本体でデータの初期値を返す関数として定義する。 データは必要な数だけ「名前:初期値」の形式で列記できる。 |
getter | state のデータに対する算出プロパティ(computed オプションに相当)。 既存のstateの値をもとに算出するためのプロパティ。 第1引数にstateを受け取り値を返す関数。 |
actions | stateの値を更新する関数。 ストアのインスタンスにthisでアクセスできる。 |
import {defineStore} from "pinia";
interface State {
count: number;
}
export const useCounterStore = defineStore("counter", {
state: (): State => {
return {
count: 0
};
},
getters: {
doubleCount: (state): number => {
return state.count * 2;
}
},
actions: {
increment(): void {
this.count++;
}
}
});
setup関数
setup関数の意味をoptionsオブジェクトに合わせて解説する。
内容 | optionsオブジェクトに沿った名称 |
変数名 = ref() | stateに相当 |
変数名 = computed() | getter |
function() | actions |
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
// state
const count = ref(0)
// getter
const doubleCount = computed(() => count.value * 2)
// action
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
どちらの構文を使用するか
Setup関数はソースが簡潔だが何を意味しているか判断する必要があり、Optionsオブジェクトでは各プロパティ名によりソースが明確だが煩雑になる。
公式ドキュメント
VueのコンポジションAPIとオプションAPIと同様に、最も使いやすいものを選択してください。
よくわからない場合は、最初にOption Stores(optionsオブジェクト)を試してください。
戻り値
defineStore()
は定義されたストアのインスタンスを生成する関数を返す。
すトアのインスタンスを生成する関数と書いているが、defineStore()の戻り値の関数はコンストラクタではなくgetter関数(useXxxxStore)となる。
戻り値のgetter関数はコンポーネントから参照できるように名前付きエクスポートする。
ストアファイルの利用
npmからinitした時点ではcounter.tsを使用したページが作成されないApp.vueにサンプルを作成する。
コンポーネントからcounter.tsでエクスポートしたuseCounterStoreをインポートして使用する。
この際、インポートしたuseCounterStore()関数は変数に格納することで、この変数がストアオブジェクトとなる。
<script setup lang="ts">
import { computed } from "vue";
import { useCounterStore } from "@/stores/counter";
const counterStore = useCounterStore();
const count = computed(
(): number => {
return counterStore.count;
}
);
const doubleCount = computed(
(): number => {
return counterStore.doubleCount;
}
);
const onIncrementClick = () => {
counterStore.increment();
};
</script>
<template>
<p>count: {{ count }}</p>
<p>doubleCount: {{ doubleCount }}</p>
<button v-on:click="onIncrementClick">加算</button>
</template>
ストアの各値の利用
ストアのstate、getter、actionの各値の利用方法が異なる。
stateとgetter
state
とgetter
はストアオブジェクト(格納した変数)に.state名
または.getter名
を記述することで、その値を利用できる。
ただし、上記のサンプルではクリック毎に値が再計算されるためstate変数もgette変数もcomputed()関数を利用して算出プロパティとする必要がある。
const 変数名 = computed(
(): データ型 => {
return ストアオブジェクト.state名;
または
return ストアオブジェクト.getter名;
}
);
action
action
を使用する場合はストアオブジェクト(格納した変数)から直接action関数を呼び出せる。
ステートオブジェクト.action関数名();
defineStore()ののgettersとactionsに引数を渡す
defineStore()の第二引数にoptionsオブジェクトを渡す場合、getters
とactions
に引数の渡す方法が異なる。
getters
gettersオブジェクトに引数を渡す場合、関数を戻り値とする。
その関数に引数を設定することで、コンポーネントからひきすうを渡せるようになる。
getters: {
getter名: (state) => {
return (引数: 引数の型): 戻り値の型 => {
stateを元に加工するデータの処理;
return 加工データ;
};
},
...
},
actions
actionsオブジェクトに引数を渡す場合は、通常の関数の引数を渡すように定義する。
actions: {
action名(引数: 引数の型): 戻り値の型 {
this.state.処理;
};
},
...
},