SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

JavaScriptフレームワーク「Vue.js」と「Nuxt.js」の活用

Webページの状態を集中管理できる「Nuxt.js」のVuexストアを使いこなそう

JavaScriptフレームワーク「Vue.js」と「Nuxt.js」の活用 第5回

Vuexストアを利用したWebページの実装方法

 Vuexストアの基本的な利用法を、健康診断の結果を入力/表示するWebページを想定した図2のサンプルで説明します。このサンプルは、氏名を入力するInputBasic、身長と体重を入力するInputPhysical、診断結果を出力するShowResultの各コンポーネントから構成されており、Vuexストアを利用して状態を管理します。

図2:Vuexストアを利用した健康診断Webページのサンプル(P001-basic)
図2:Vuexストアを利用した健康診断Webページのサンプル(p001-basic)

 Nuxt.jsでは、storeフォルダー配下のJavaScriptファイルにVuexストアを実装します。図2のサンプルで利用するVuexストアの実装は、リスト1の通りです。

[リスト1]Vuexストアの実装(p001-basic/store/index.js)
// ステート ...(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の通り実装します。

[リスト2]氏名を入力するコンポーネント(p001-basic/components/InputBasic.vue)
<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オブジェクトを引数に設定して実行されます。

[リスト3]ステートの身長と体重を更新するミューテーションを実行する処理(p001-basic/components/InputPhysical.vue)
this.$store.commit('setPhysical', {
  height: this.height,
  weight: this.weight
})

 診断結果を表示するShowResultコンポーネントの実装はリスト4の通りです。

[リスト4]診断結果を表示するコンポーネント(p001-basic/components/ShowResult.vue)
<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の通り実装できます。

[リスト5]ゲッターの実装(p002-getter/store/index.js)
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.<ゲッター名>」というプロパティで計算結果を取得できます。

[リスト6]ゲッターのプロパティ利用例(p002-getter/components/ShowResult.vue)
<div>BMI:{{ $store.getters.BMI.toFixed(2) }}</div>

 リスト5(2)は、名前に接尾辞を付与する関数を返却するゲッターnameWithSuffixを実装しています。ゲッターで関数を返却すると、コンポーネントではリスト7の通り「$store.getters.<ゲッター名>(<引数>)」というメソッドとして実行できます。

[リスト7]ゲッターのメソッド利用例(p002-getter/components/ShowResult.vue)
<div>{{ $store.getters.nameWithSuffix("さん") }}</div>

次のページ
非同期処理を実行できるアクション

この記事は参考になりましたか?

JavaScriptフレームワーク「Vue.js」と「Nuxt.js」の活用連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト  吉川 英一(ヨシカワ エイイチ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/11994 2020/03/02 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー