状態を管理してくれる Vuex ストアは、あらゆる大規模アプリケーションにとても役に立ちます。Nuxt.js が Vuex をコアに組み入れたのはそのような理由からです。
Nuxt.js は store
ディレクトリを探索し存在するときには以下を実行します:
store
オプションをルートの Vue インスタンスに追加しますNuxt.js では 2つのモードのストア があります。どちらか好みのほうを選んで使ってください:
store
ディレクトリ内のすべての *.js
ファイルが 名前空間付きモジュール に変換されます(index
はルートモジュールとして存在します)store/index.js
がストアインスタンスを返しますモードに関わらず、サーバーサイドで不要な共有状態を避けるため、state
の値は常に function
でなければなりません。
Nuxt.js では
store
ディレクトリ内にモジュールと対応するファイルを持つことができます。
まずはじめに、store/index.js
内でステートを関数として、ミューテーション、アクションをオブジェクトとしてシンプルにエクスポートします:
export const state = () => ({
counter: 0
})
export const mutations = {
increment (state) {
state.counter++
}
}
また、次のような store/todos.js
ファイルを作成できます:
export const state = () => ({
list: []
})
export const mutations = {
add (state, text) {
state.list.push({
text: 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
モジュールを下記のように使うことができます:
<template>
<ul>
<li v-for="todo in todos">
<input type="checkbox" :checked="todo.done" @change="toggle(todo)">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</li>
<li><input placeholder="What needs to be done?" @keyup.enter="addTodo"></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
ディレクトリにあるサブディレクトリの実装なしにトップレベルの定義に対しても機能します。
ステートの例です。store/state.js
を作成し、以下の行を追加します。
export default () => ({
counter: 0
})
対応するミューテーションは store/mutations.js
にあります。
export default {
increment (state) {
state.counter++
}
}
オプションでモジュールファイルを state.js
、actions.js
、 mutations.js
、getters.js
といった別々のファイルに分離することができます。index.js
ファイルで状態やゲッター、ミューテーションを持ちながら、アクションを別のファイルを分けた場合もまた適切に認識されます。
情報: 分割ファイルモジュールを使っている時にアロー関数を使うと、
this
は構文的にしか利用できないことを覚えておく必要があります。 レキシカルスコープは単にthis
が常にアロー関数の所有者を参照することを意味しています。もしアロー関数が含まれていない場合、this
は undefined になります。解決策として「普通の」関数でスコープを作ると、そこでthis
を使うことができるようになります。
プラグインを store/index.js
ファイルに置くことで、ストア(モジュールモード)に追加できます:
import myPlugin from 'myPlugin'
export const plugins = [ myPlugin ]
export const state = () => ({
counter: 0
})
export const mutations = {
increment (state) {
state.counter++
}
}
プラグインについてのさらに詳しい情報は Vuex ドキュメント を参照してください。
fetch メソッドは、ページがレンダリングされる前に、データをストアに入れるために使われます。コンポーネントのデータをセットしないという点を除いては data メソッドとよく似ています。
fetch メソッドについてより深く理解するためには ページの fetch メソッド API を参照してください。
nuxtServerInit
というアクションがストア内に定義されているときは、Nuxt.js はそれをコンテキストとともに呼び出します(ただしサーバーサイドに限ります)。サーバーサイドからクライアントサイドに直接渡したいデータがあるときに便利です。
例えば、サーバーサイドでセッションを持っていて、接続しているユーザーに req.session.user
を通じてアクセスできるとします。認証されたユーザーにストアを渡すために store/index.js
下記のように書き換えます:
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}
Vuex ストアの モジュール モードを使っている場合はなら、プライマリモジュール(
store/index.js
)のみ、このアクションを受け取ることができます。その他のモジュールのアクションでも使いたい場合は、プライマリモジュールからチェインする必要があります。
コンテキストは、asyncData
や fetch
メソッドと同様に nuxtServerInit
に第二引数として渡されます。
注意: 非同期の
nuxtServerInit
アクションは nuxt サーバーの待機を可能にするために Promise を返さなければなりません
actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
Strict モードは dev モードではデフォルトで有効化されており、production モードでは無効化されています。strict モードを dev で無効化するには、以下の例を参照してください。
export const strict = false
この機能は Nuxt 3 で廃止し、削除される予定です。
クラシックモードでストアを使うには、Vuex インスタンスを返す関数がエクスポートされている store/index.js
ファイルを作る必要があります。
import Vuex from 'vuex'
const createStore = () => {
return new Vuex.Store({
state: () => ({
counter: 0
}),
mutations: {
increment (state) {
state.counter++
}
}
})
}
export default createStore
vuex
は Nuxt.js によって取り込まれているため、別途インストールする必要はありません。
クラシックモードを有効にすると、コンポーネント内で this.$store
を使うことができます:
<template>
<button @click="$store.commit('increment')">{{ $store.state.counter }}</button>
</template>
間違いを見つけた、またはドキュメントに貢献したいですか? GitHub でこのページを編集する