#はじめに
おはようございます。こんにちは。こんばんは。
Watatakuです。
今回は以前こちらで書かせていただいた内容の中で「次回Vuexやるよー」と言っておきながらやっていなかったのでやっていきます。
#Vuexとは
Vuex は複数のコンポーネント間で状態を共有するために使われる状態管理のライブラリです。
Vueのコンポーネントから状態管理の部分をVuex側に寄せることで、コンポーネント間のプロパティ渡しの連鎖による複雑さを回避できます。
#使い方
本来ならVuexをインストールしたりゴニョゴニョしないといけませんが、Nuxt.jsでVuexストアを使う場合は store ディレクトリ配下にファイルを配置することで管理ができます。
##storeディレクトリ配下にモジュールを配置する
ここでは ./store/todo.js として以下のファイルを作成するのですが、Nuxt.jsでは storeディレクトリ配下のパスがストアに名前空間を与えます。つまり todo
という名前空間になります。
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
}
}
state
の部分で変数(プロパティ)※vueファイルで言うところのdata(){ return { } }
の中を定義します。
上の例では配列のlistができています。
さらにmutations
の中でstateの状態を変更させるメソッドを定義します。
では、次にどのようにして.vue
から上のstate
を扱うか見てみましょう。
##componentからstateを呼び出す
<template>
<div>
<h1>TODOLIST</h1>
<ul>
<li v-for="todo in todos" :key="todo.id">
<input :checked="todo.done" @change="toggle(todo)" type="checkbox" />
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="removeTodo(todo)">remove</button>
</li>
<li>
<input @keyup.enter="addTodo" placeholder="What needs to be done?" />
</li>
</ul>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
computed: {
todos() {
return this.$store.state.todo.list
}
},
methods: {
addTodo(e) {
this.$store.commit('todo/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todo/toggle'
}),
removeTodo(todo) {
this.$store.commit('todo/remove', todo)
}
}
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
※ここではstate周りのことしか解説しません。
解説しやすいように<script>
タグの部分を剥き出します。
import { mapMutations } from 'vuex'
export default {
computed: {
todos() {
return this.$store.state.todo.list
}
},
methods: {
addTodo(e) {
this.$store.commit('todo/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todo/toggle'
}),
removeTodo(todo) {
this.$store.commit('todo/remove', todo)
}
}
}
###storeに格納した値の取り出し方
上の例では、この部分で取得できます。
this.$store.state.todo.list
つまり、todo.js
で定義したlist
プロパティの値を指しています。
export const state = () => ({
list: []
});
###storeに値を格納する
上の例では、この部分で取得できます。
this.$store.commit('todo/add', e.target.value)
つまり、todo.js
で定義したtodo/add
メソッドを入力された値を引数として実行してくださいと言うことです。
export const mutations = {
add(state, text) {
state.list.push({
text,
done: false
})
},
//以下省略
}
#TIPS
##getters
要は、vuexのstateを取得する際のゲッターメソッドです。
基本的にstoreからの取得はゲッターメソッドを使って取得するので。上で作ったTODOリストのstateの取得をゲッターメソッドにします。
以下をstore/todo.js
に追加してください。
export const getters = {
getList (state) {
return state.list
}
}
さらにpage/todo.vue
を下記のように変更してください。
<template>
<div>
<h1>TODOLIST</h1>
<ul>
<li v-for="todo in todos" :key="todo.id">
<input :checked="todo.done" @change="toggle(todo)" type="checkbox" />
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="removeTodo(todo)">remove</button>
</li>
<li>
<input @keyup.enter="addTodo" placeholder="What needs to be done?" />
</li>
</ul>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
computed: {
todos() {
return this.$store.getters['todo/getList']
}
},
methods: {
addTodo(e) {
this.$store.commit('todo/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todo/toggle'
}),
removeTodo(todo) {
this.$store.commit('todo/remove', todo)
}
}
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
gettersを使うときはstoreでgetterメソッドを定義し**this.$store.getters['todo/getList']**で取得します。
##actions
最後にactionsを用いてTODOリストを行なっていきます。
今回のTODOリストではactionsは特に必要ないですが、解説のためactions経由します。
todo.js
に以下を追加してください。
export const actions = {
setList(vuexContext, text) {
vuexContext.commit('add', text)
},
toggle(vuexContext, event) {
vuexContext.commit('toggle', event)
},
remove(vuexContext, todo) {
vuexContext.commit('remove', todo)
}
}
最後にtodo.vue
も変更します。
<template>
<div>
<h1>TODOLIST</h1>
<ul>
<li v-for="todo in todos" :key="todo.id">
<input :checked="todo.done" @change="toggle(todo)" type="checkbox" />
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="removeTodo(todo)">remove</button>
</li>
<li>
<input @keyup.enter="addTodo" placeholder="What needs to be done?" />
</li>
</ul>
</div>
</template>
<script>
export default {
computed: {
todos() {
return this.$store.getters['todo/getList']
}
},
methods: {
addTodo(e) {
this.$store.dispatch('todo/setList', e.target.value)
e.target.value = ''
},
toggle(e) {
this.$store.dispatch('todo/toggle', e)
},
removeTodo(todo) {
this.$store.dispatch('todo/remove', todo)
}
}
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
mutations
,actions
の違いは非同期操作を行うときにはactions
に書くと言う認識で一先ずOKです。
#まとめ
- state: data保管庫
- getters: stateの情報を取得。別gettersの呼び出しも可能
- actions: storeの上書き以外の処理や非同期通信。別actionsの呼び出しも可能
- mutations: stateの上書き(代入)
【基本の呼び出し方】
- state: 直接呼び出すことはない
- getters: (return) this.$store.getters['*******']
- actions: this.$store.dispatch('*****')
- mutations: this.$store.commit('*******')
#参考にしたもの
#最後に
以上が基本的なVuexの使い方です。
これを利用することでコードがすっきり書けpropsや$emitのバケツリレーなどが防げます。
もし間違い等アドバイスやご指摘があればご連絡お願いします。
次回はここでも実はちょいと出てきたのですがVuexヘルパーを解説していきます。