Vuexストアを利用したWebページの実装方法
Vuexストアの基本的な利用法を、健康診断の結果を入力/表示するWebページを想定した図2のサンプルで説明します。このサンプルは、氏名を入力するInputBasic、身長と体重を入力するInputPhysical、診断結果を出力するShowResultの各コンポーネントから構成されており、Vuexストアを利用して状態を管理します。
Nuxt.jsでは、storeフォルダー配下のJavaScriptファイルにVuexストアを実装します。図2のサンプルで利用するVuexストアの実装は、リスト1の通りです。
// ステート ...(1)
export const state = () => ({
name: '', // 氏名
height: 0, // 身長
weight: 0 // 体重
})
// ミューテーション ...(2)
export const mutations = {
// 氏名を更新 ...(2a)
setName(state, name) {
state.name = name
},
// 身長と体重を更新 ...(2b)
setPhysical(state, payload) {
state.height = payload.height
state.weight = payload.weight
}
}
(1)がステートで、氏名、身長、体重を定義しています。(2)はステートを更新するミューテーションです。第1引数にステートを表すstate変数、第2引数に更新内容を表す変数をとるメソッドで実装します。(2a)では氏名の文字列、(2b)では身長と体重を含むJavaScriptオブジェクトを引数から受け取って、(1)で定義したステートを更新します。
このVuexストアを利用して、氏名を入力するInputBasicコンポーネントを、リスト2の通り実装します。
<template>
<div class="component">
<!-- テキストボックス ...(1)-->
氏名:<input v-model="name" v-on:input="onInput">
</div>
</template>
<script>
export default {
data() {
return {
name: '' // テキストボックスの入力内容 ...(2)
}
},
methods: {
onInput() { // テキストボックス変更時の処理 ...(3)
this.$store.commit('setName', this.name) // ミューテーション ...(4)
}
}
}
</script>
(1)のテキストボックスは、v-modelディレクティブの指定によって入力内容が(2)のname変数に反映され、内容の変更時はv-onディレクティブの指定で(3)のonInputメソッドが実行されます。onInputメソッド内では、Vuexストア(this.$store)のcommitメソッド(4)でミューテーションを実行します。commitメソッドの第1引数にミューテーションの名前を、第2引数にはミューテーションに渡す引数を設定します。(4)の処理では、リスト1(2a)のsetNameメソッドが、this.nameを引数に設定して実行されます。
同様に、身長と体重を入力するInputPhysicalコンポーネントでステートを更新する処理はリスト3です。この場合、リスト1(2b)のsetPhysicalメソッドが、身長と体重を格納したJavaScriptオブジェクトを引数に設定して実行されます。
this.$store.commit('setPhysical', {
height: this.height,
weight: this.weight
})
診断結果を表示するShowResultコンポーネントの実装はリスト4の通りです。
<template>
<div class="component">
<div>{{ $store.state.name }}さん</div><!--(1)-->
<div>BMI:{{ BMI.toFixed(2) }}</div>
<div>(身長:{{ $store.state.height }}cm、体重:{{ $store.state.weight }}kg)</div>
</div>
</template>
<script>
export default {
computed: {
BMI() {
return this.$store.state.weight
/ Math.pow((this.$store.state.height / 100), 2) // ...(2)
}
}
}
</script>
<template>内では(1)の通り「$store.state.<変数名>」で、<script>内では(2)の通り「this.$store.state.<変数名>」で、ステートの変数を参照できます。(2)では、身長と体重からBMIを計算する導出プロパティBMIを実装して利用しています。なお、導出プロパティBMIを参照する<template>内の「BMI.toFixed(2)」記述は、BMIを小数第2位まで表示する処理です。
このサンプルでは、複数のコンポーネントがVuexストアを利用して、Webページの状態を共有できることを説明しました。以下ではこのサンプルを改造しながら、Vuexストアのさまざまな機能を説明していきます。
状態の取得を便利にするゲッター
Vuexストアでは、ステートの内容を加工して取り出す「ゲッター」を利用できます。ゲッターはVuexストアに、リスト5の通り実装できます。
export const getters = {
// プロパティスタイル ...(1)
BMI(state) {
return state.weight / (Math.pow(state.height / 100, 2))
},
// メソッドスタイル ...(2)
nameWithSuffix(state) {
return function (suffix) {
return state.name + suffix
}
}
}
リスト5(1)では、BMIを計算して返却するゲッターBMIを実装しています。ゲッターで値(計算結果)を返却すると、コンポーネントではリスト6の通り「$store.getters.<ゲッター名>」というプロパティで計算結果を取得できます。
<div>BMI:{{ $store.getters.BMI.toFixed(2) }}</div>
リスト5(2)は、名前に接尾辞を付与する関数を返却するゲッターnameWithSuffixを実装しています。ゲッターで関数を返却すると、コンポーネントではリスト7の通り「$store.getters.<ゲッター名>(<引数>)」というメソッドとして実行できます。
<div>{{ $store.getters.nameWithSuffix("さん") }}</div>
