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ではミューテーションに非同期処理を含むことができないので、ステートの更新に非同期処理が必要な場合は、コンポーネントからアクションを実行して、その中でミューテーションを実行するようにします。実装例をリスト8に示します。

[リスト8]アクションの実装(p003-action/store/index.js)
export const actions = {
  // setNameミューテーションを実行 ...(1)
  doSetName(context, name) {
    context.commit('setName', name)
  },
  // setPhysicalミューテーションを実行 ...(2)
  doSetPhysical({ commit }, payload) {
    commit('setPhysical', payload)
  },
  // setPhysicalミューテーションを遅延実行 ...(3)
  doSetPhysicalDelayed({ commit }, payload) {
    return new Promise(function (resolve, reject) {
      setTimeout(function () {
        commit('setPhysical', payload)
        resolve(payload)
      }, 1000)
    })
  }
}

 (1)はsetNameミューテーションを実行するアクションで、第1引数に渡されるcontextのcommitメソッドでsetNameミューテーションを実行(commit)します。同様に(2)はsetPhysicalミューテーションを実行します(引数の「{ commit }」記法については後述の補足を参照)。(3)は非同期処理で、setPhysicalミューテーションを1秒後に実行します。Promiseを返却すると、呼び出し元で処理完了を検知できます(詳細は後述します)。

 Vuexストアを利用するコンポーネントでは、this.$store.dispatchメソッドでアクションを実行(Dispatch)できます。第1引数にアクション名、第2引数にアクションに渡す引数を設定します。

[リスト9]アクションを実行する実装(p003-action/components/InputBasic.vue)
this.$store.dispatch('doSetName', this.name)

 また、リスト8(3)の通りアクションでPromiseを返却すると、コンポーネントでPromiseを受け取って、アクション実行完了後の処理を実装できます。

[リスト10]非同期アクションを実行する実装(p003-action/components/InputPhysical.vue)
this.$store.dispatch('doSetPhysicalDelayed', { // アクション実行
  height: this.height,
  weight: this.weight
})
.then(payload => { // アクション実行完了後の処理 ...(1)
  this.payload = JSON.stringify(payload, null, ' ')
})

 リスト10では、入力して1秒経過後にVuexストアに変更が反映されるとともに、アクション実行完了後の処理(1)で、アクションに与えたパラメーターが画面表示されます。実装の詳細はサンプルコード(p003-action)を参照してください。

[補足]アクションの記述を簡略化できる「引数分割束縛」

 リスト8(2)の、引数を中カッコで囲んだ「{ commit }」記述は、Vuexの公式ページで「引数分割束縛(argument destructuring)」と説明されています。関数の引数に渡されるオブジェクトから、中カッコ内のプロパティやメソッド(ここでは「commit」メソッド)を取り出して、関数内で利用できるようにします。引数分割束縛を利用して関数内の記述を簡略化できます(リスト11)。

[リスト11]引数分割束縛を利用した記述の簡略化
doSetPhysical(context, payload) {
  context.commit('setPhysical', payload) // ...(1)
}
↓
// 第1引数に渡されるオブジェクトからcommitメソッドを取り出す
doSetPhysical({ commit }, payload) {
  commit('setPhysical', payload) // このcommitは(1)のcontext.commitに相当
}

 引数分割束縛では、メソッドの引数に「分割代入」を行っています。分割代入の詳細はMozillaのリファレンスを参照してください。

複雑なVuexストアをモジュールに分割

 Webページの機能が増えていくと、Vuexストアの内容が複雑になっていきます。こういった場合、Vuexストアをモジュールに分割できます。実装方法を図3のサンプルで説明します。これまでの健康診断のサンプルに、血液検査の結果を入力できるInputBloodコンポーネントを追加し、基本情報(InputBasicコンポーネント)にIDの項目を追加しました。

図3:改良した健康診断Webページのサンプル(p004-module)
図3:改良した健康診断Webページのサンプル(p004-module)

 Vuexストアをモジュールに分割するには、storeフォルダー配下にindex.js以外のJavaScriptファイルを配置して、それぞれにVuexストアを実装します。このサンプルでは、基本情報(IDと氏名)をindex.js、身体測定の情報(身長と体重)をphysical.js、血液検査の情報(肝臓のγ-GT)をblood.jsでそれぞれ管理します。

図4:モジュール化したVuexストアのJavaScriptファイル(p004-module)
図4:モジュール化したVuexストアのJavaScriptファイル(p004-module)

 blood.jsの内容をリスト12に示します。γ-GTを保持するステート(1)と、ステートを更新するミューテーション(2)、γ-GTが正常値かどうかを判定するゲッター(3)、ミューテーションを呼び出すアクション(4)を実装しています。blood.js以外のVuexストアは、サンプルコードを参照してください。

[リスト12]血液検査の情報を管理するVuexストア(p004-module/store/blood.js)
// ステート ...(1)
export const state = () => ({
  gammaGT: 0 // 肝臓のγ-GT
})
// ミューテーション ...(2)
export const mutations = {
  setValue(state, payload) {
    state.gammaGT = payload.gammaGT;
  }
}
// ゲッター ...(3)
export const getters = {
  isGammaGTNormal(state) {
    return state.gammaGT <= 70 // γ-GTの正常値:70以下
  }
}
// アクション ...(4)
export const actions = {
  doSetValue({ commit }, payload) {
    commit('setValue', payload)
  }
}

 モジュールに分割された(index.js以外の)Vuexストアのステートやゲッターを参照するには、リスト13の通り、Vuexストアのモジュール名(「blood」)を設定します。

[リスト13]モジュールに分割されたストアの内容参照(p004-module/components/ShowResult.vue)
γ-GT:{{ $store.state.blood.gammaGT }}
→{{ $store.getters["blood/isGammaGTNormal"] ? "正常値" : "異常値" }}です。

 また、モジュールに分割されたVuexストアのアクションやミューテーションを実行するには、第1引数に設定する名前を「<モジュール名>/<メソッド名>」とします。

[リスト14]モジュールに分割されたストアのアクション実行(p004-module/components/InputBlood.vue)
this.$store.dispatch('blood/doSetValue', {
  gammaGT: this.gammaGT
})

まとめ

 本記事では、Vue.jsで状態管理に用いるVuexストアを、Nuxt.jsで利用する方法を説明しました。Vuexストアを利用することで、Webページ全体の状態を一括管理して、複数のコンポーネントから不整合なく参照・更新できます。

 次回は、HTTPクライアントライブラリAxiosを利用して、コンポーネントやVuexストアのデータを非同期取得する、Nuxt.jsの非同期処理について説明します。

参考資料

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
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」など、さまざまなカンファレンスを企画・運営しています。

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

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

メールバックナンバー