ストア

store  ディレクトリには Vuex ストアに関するファイルが含まれています。Vuex ストアは Nuxt.js に付属していてすぐに使えますが、デフォルトでは無効化されています。このディレクトリ内に index.js ファイルを作成することで、ストアが有効化されます。

このディレクトリは追加の設定無しにリネームすることはできません。

ストアを使って状態を管理するのは、どういった大きなアプリケーションを作るにあたっても重要なことです。それがなぜ Nuxt.js がそのコアに Vuex を組み込んでいるかの理由です。

ストアを有効化する

Nuxt.js は store ディレクトリを確認します。もし隠しファイルや README.md ではないファイルが含まれていたら、ストアは有効化されます。これは Nuxt が以下を行うことを意味しています:

  1. Vuex をインポートする
  2. ルートの Vue インスタンスに store オプションを追加します。

モジュール

store ディレクトリの中にあるすべての  .js ファイルは名前空間付きモジュールに変換されます(index はルートモジュールになります)。state の値は不必要に状態がサーバサイドで共有されてしまうことを避けるため、常に function であるべきです。

はじめに、ステートを関数で、ミューテーションとアクションをオブジェクトでエクスポートしましょう。

store/index.js
export const state = () => ({
  counter: 0
})

export const mutations = {
  increment(state) {
    state.counter++
  }
}

次に、store/todos.js ファイルを作成しましょう:

store/todos.js
export const state = () => ({
  list: []
})

export const mutations = {
  add(state, text) {
    state.list.push({
      text,
      done: false
    })
  },
  remove(state, { todo }) {
    state.list.splice(state.list.indexOf(todo), 1)
  },
  toggle(state, todo) {
    todo.done = !todo.done
  }
}

ストアは以下のように生成されるでしょう:

new Vuex.Store({
  state: () => ({
    counter: 0
  }),
  mutations: {
    increment(state) {
      state.counter++
    }
  },
  modules: {
    todos: {
      namespaced: true,
      state: () => ({
        list: []
      }),
      mutations: {
        add(state, { text }) {
          state.list.push({
            text,
            done: false
          })
        },
        remove(state, { todo }) {
          state.list.splice(state.list.indexOf(todo), 1)
        },
        toggle(state, { todo }) {
          todo.done = !todo.done
        }
      }
    }
  }
})

また、pages/todos.vue では todos モジュールを以下のように利用することができます:

pages/todos.vue
<template>
  <ul>
    <li v-for="todo in todos" :key="todo.text">
      <input :checked="todo.done" @change="toggle(todo)" type="checkbox">
      <span :class="{ done: todo.done }">{{ todo.text }}</span>
    </li>
    <li><input @keyup.enter="addTodo" placeholder="What needs to be done?"></li>
  </ul>
</template>

<script>
import { mapMutations } from 'vuex'

export default {
  computed: {
    todos () {
      return this.$store.state.todos.list
    }
  },
  methods: {
    addTodo (e) {
      this.$store.commit('todos/add', e.target.value)
      e.target.value = ''
    },
    ...mapMutations({
      toggle: 'todos/toggle'
    })
  }
}
</script>

<style>
.done {
  text-decoration: line-through;
}
</style>

モジュールメソッドはストアディレクトリにサブディレクトリを追加することなく、トップレベルでの定義に利用することができます。

ステートの例: 以下のように store/state.js を作成します。

export default () => ({
  counter: 0
})

対応するミューテーションは store/mutations.js に置くことができます

store/mutations.js
export default {
  increment(state) {
    state.counter++
  }
}

ストアでのプラグイン

store/index.js ファイルの中に置くことで、ストアにプラグインを追加することができます:

store/index.js
import myPlugin from 'myPlugin'

export const plugins = [myPlugin]

export const state = () => ({
  counter: 0
})

export const mutations = {
  increment(state) {
    state.counter++
  }
}

プラグインについてより詳細な情報はこちら: Vuex のドキュメント

nuxtServerInit アクション

ストアに nuxtServerInit アクションが定義されていて、かつ universal モードの場合、Nuxt.js はコンテキストを渡してこれを呼び出します(サーバサイドのみ)。これはサーバにある何らかのデータを直接クライアントサイドに渡すときに便利です。

例えば、サーバサイドにセッションがあり、req.session.user で接続したユーザにアクセスできるとしましょう。認証されたユーザをストアに渡すには、store/index.js を以下のように変更します:

store/index.js
actions: {
  nuxtServerInit ({ commit }, { req }) {
    if (req.session.user) {
      commit('user', req.session.user)
    }
  }
}

このアクションは受け取るのは(store/index.js 内の)プライマリモジュールだけです。ここから他のモジュールのアクションに呼び出しを繋いでいく必要があります。

コンテキストasyncData メソッドのように、nuxtServerInit の第 2 引数として渡されます。

nuxt generate が走った場合、nuxtServerInit は全ての動的に生成されたルートで実行されます。

非同期の nuxtServerInit アクションは、Promise を返すか async/await を利用して nuxt サーバが待機できるようにしなければなりません。

store/index.js
actions: {
  async nuxtServerInit({ dispatch }) {
    await dispatch('core/load')
  }
}

Vuex 厳格モード

厳格モードは dev モードではデフォルトで有効になっていて、production モードでは無効になっています。 厳格モードを dev モードでも無効化するには、store/index.js を下記の例に従ってください:

export const strict = false

間違いを見つけた、またはドキュメントに貢献したいですか? GitHub でこのページを編集する