【Nuxt2】storeでaxios通信と共通データづくり

Nuxt.jsをここ数ヶ月使用してきて下記のような困りごとが出てきました。
axiosでAPI通信をし取得したデータをどっかで保持して全部のページで使いたい!
どこのコンポーネントでも共通で使えるデータが欲しい !
必要な情報をどこからでも使えるようにstoreに保持できるとの事だったので調べてみました。
今回はVuexを利用したNuxt2での方法です。

storeでできること

storeを使うことで、アプリケーションの状態やデータを保持することができます。
ログインのステータスを保持したり、複数ページで利用する値を管理する際に使用します。

storeにはモジュールモードとクラシックモードがありますが、クラシックモードはNuxt3では廃止の予定です。

モジュールモード: store ディレクトリ内のすべての *.js ファイルが 名前空間付きモジュール に変換されます(index はルートモジュールとして存在します)
クラシックモード (廃止予定): store/index.js がストアインスタンスを返します

(参考)
https://develop365.gitlab.io/nuxtjs-2.8.X-doc/ja/guide/vuex-store/
そのため、この記事ではモジュールモードでの記述で説明していきます。

axiosのレスポンスを保持してみる

state・mutation・actionsを使用してAPIからデータ取得します。

.fa-hand-point-right{ color: #fcb900 }
state
要素の管理をするもの
dataプロパティと同じようなものと考える

mutations
状態の変更をするもの

actions
非同期処理を書くことができる
mutationを経由して(commit)stateを更新する
各コンポーネントからはactionで定義した処理が呼ばれる

.code.api::after{ content: ‘store/api.js’; background: #969998; color: #fff; }


import axios from 'axios'

export const state = () => ({
  list: [],
});

export const mutations = {
  setList(state, list) {
    state.list = list;
  },
};

export const actions = {
  async getList ({commit}) {
    const response = await this.$axios.$get('APIのURL')
    commit('setList', response);
  }
};

ちなみに、リロードするとstoreに保存されたデータは消えてしまいます。

永続化が必要であればvuex-persistedstateとかを使った方が良いです。

Vuexのヘルパーを使ってstoreで得たデータを呼び出します。

コンポーネントをバインドするヘルパー
コンポーネントのcomputedオプションを作成【状態を呼び出す】
mapState
mapGetters
コンポーネントのmethodsオプションを作成を作成【状態の変更】
mapActions
mapMutations
(参考)
https://vuex.vuejs.org/ja/api/#mapstate

mapActionsを使ってstoreのactionsのgetList()を呼んで
mountedでgetList()を動かして
mapStateで取得しています。

.code.vue::after{ content: ‘component/data.vue’; background: #969998; color: #fff; }


<template>
<p>{{ list }}</p>
</template>

<script>
import { mapActions, mapState } from 'vuex'

export default {
  mounted () {
    this.getList()
  },
  methods: {
    ...mapActions({
      getList: 'api/getList',
    }),
  },
  computed: {
    ...mapState({
      list: (state) => state.api.list,
    }),
  },
}
</script>

共通で使えるデータをつくってみる

共通で使用できるデータとしてJSONデータを作成します。

.code.json::after{ content: ‘assets/json/ruby.json’; background: #969998; color: #fff; }


[
    { "text": "設定", "ruby": "せってい" },
    { "text": "送信", "ruby": "そうしん" },
    { "text": "返信", "ruby": "へんしん" },
    { "text": "検索", "ruby": "けんさく" },
]

storeフォルダに、json.jsを作成してruby.jsonを読み込ませます。

.code.data::after{ content: ‘store/json.js’; background: #969998; color: #fff; }


import jsonData from '@/assets/json/ruby.json'

export const state = () => ({
  data: jsonData,
})

export const getters = {
  // 全件表示
  getAll: (state) => {
    return state.data
  },
    // keyで検索
  getDataByText: (state) => (text) => {
    return state.data.find(data => data.text === text)
  },
}

あとは使いたい箇所で呼び出しましょう!

全件をforで回してもよし。

.code.vue::after{ content: ‘component/data.vue’; background: #969998; color: #fff; }


<template>
<ul>
  <template v-for="ruby in getAll">
      <li :key="kana.index">{{ ruby.text }}</li>
  </template>
</ul>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters({
      getAll: 'json/getAll',
    }),
  },
}
</script>

子コンポーネントなんかでkeyで検索させて表示させれば、ふりがなを表示させたりなんて使い方もできます。

.code.vue::after{ content: ‘component/data.vue’; background: #969998; color: #fff; }


<template>
  <ruby>
    <rb>{{ data(translateText).text }}</rb>
    <rp>(</rp><rt>{{ data(translateText).kana }}</rt><rp>)</rp>
  </ruby>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  props:{
      translateText: String,
  },
  computed: {
    ...mapGetters({
      data: 'json/getDataByText',
    }),
  },
}
</script>

できた!