公式定義#
Vuex は、Vue.js アプリケーションのために設計された状態管理パターンです。それは、アプリケーションのすべてのコンポーネントの状態を集中管理し、対応するルールに従って状態が予測可能な方法で変化することを保証します。
Vuex のインジェクション#
import store from "./store";
new Vue({
store,
});
store.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
msg: "こんにちは、世界",
},
mutations: {},
actions: {},
});
状態の取得#
任意のコンポーネントでこの msg
を次のように取得できます。
<template>
<div class="about">
<h1>これはaboutページです</h1>
<h2>{{$store.state.msg}}</h2>
</div>
</template>
状態の変更#
mutations
に状態を変更するメソッドを提供します。
mutations: {
setMsg(state, newMsg) {
state.msg = newMsg
}
}
そして、actions
で変更のリクエストをコミットします。
actions: {
setMsg ({ commit }) {
commit('setMsg', 'こんにちは')
}
}
他のコンポーネントで変更のアクションをトリガーします。
<template>
<div class="about">
<h1>これはaboutページです</h1>
<h2>{{$store.state.msg}}</h2>
</div>
</template>
<script>
export default {
mounted () {
this.$store.dispatch('setMsg')
}
}
</script>
考察#
上記の例は単純な状態管理の一例です。state
は状態を保持し、mutations
は状態を変更するメソッドを提供し、actions
は状態の変更メソッドをトリガーし、変更データをコミットします。ただし、この例には明らかな問題があります。誰でも(dispatch
)状態を変更できるということです。
名前空間#
プロジェクトが複雑になる場合、状態の変更に名前空間を使用することができます。名前空間を使用するには、vuex
の modules
を使用する必要があります。modules
はオブジェクトであり、state
、mutations
、actions
から構成されます。違いは、namespaced
プロパティが追加されていることです。
状態の変更の 3 つの方法#
dispatch#
まず、以前のコンテンツを modules
に抽出します。
store.js
import Vue from "vue";
import Vuex from "vuex";
import home from "./modules/home";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
home,
},
});
./modules/home.js
export default {
namespaced: true,
state: {
msg: "こんにちは、世界",
},
actions: {
setMsg({ commit }) {
commit("setMsg", "こんにちは");
},
},
mutations: {
setMsg(state, newMsg) {
state.msg = newMsg;
},
},
};
最後に状態の取得と変更を行います。
<template>
<div class="about">
<h1>これはaboutページです</h1>
<h2>{{$store.state.home.msg}}</h2>
</div>
</template>
<script>
export default {
mounted () {
this.$store.dispatch('home/setMsg')
}
}
</script>
最後の変更時と以前の違いに注意してください。状態の取得と状態の変更の両方に home
が追加されていますが、使用のハードルが高くなりました。ただし、少なくともどのモジュールの状態を操作しているかを識別できるようになりました。
上記の例では、modules
を使用して状態を変更する別の等価な方法があります。
mapActions#
<template>
<div class="about">
<h1>これはaboutページです</h1>
<h2>{{$store.state.home.msg}}</h2>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions('home', ['setMsg'])
},
mounted () {
this.setMsg()
}
}
</script>
mapActions
を実行すると、オブジェクトが返され、展開されるため、現在のインスタンスに setMsg
メソッドが追加されます。このメソッドを呼び出すと、状態が変更されます。
createNamespacedHelpers#
上記の 2 つの方法には明らかな問題があります。現在のコンポーネントで変更する必要がある状態が多数ある場合、home
のレベルが多くなります。vuex
の createNamespacedHelpers
メソッドを使用すると、この問題を簡単に解決できます。
<template>
<div class='about'>
<h1>これはaboutページです</h1>
<h2>{{$store.state.home.msg}}</h2>
</div>
</template>
<script>
import { createNamespacedHelpers } from 'vuex'
const { mapActions } = createNamespacedHelpers('home')
export default {
methods: {
...mapActions(['setMsg'])
},
mounted () {
this.setMsg()
}
}
</script>
値の取得を簡略化#
以前の例では、値の取得について触れていませんでしたが、実際の作業ではこの方法は推奨されません。vuex
には、値の取得を簡略化する mapState
メソッドが用意されています。
<template>
<div class='about'>
<h1>これはaboutページです</h1>
<h2>{{msg}}</h2>
</div>
</template>
<script>
import { createNamespacedHelpers } from 'vuex'
const { mapActions, mapState } = createNamespacedHelpers('home')
export default {
computed: {
...mapState(['msg'])
},
methods: {
...mapActions(['setMsg'])
},
mounted () {
this.setMsg()
}
}
</script>
変数の抽出#
setMsg
という単語が出現する回数を思い出してください。コンポーネント内で使用される場合と、store
や modules
内で使用される場合があります。この場合、setMsg
を抽出して定数として保存することが推奨されます。
./store/action-type.js
export const SET_MSG = "setMsg";
使用する際には、直接 setMsg
を使用することを避けるようにし、自分自身や他の人がメンテナンスしやすくします。
結論#
vuex
の利便性は言うまでもありません。プロジェクトの複雑さに応じて、段階的なアプローチを提供しています。プロジェクトが非常にシンプルな場合、基本的な要件を満たすために modules
を使用する必要はありません。複雑さが増すと、modules
が選択肢になります。モジュールの数が多くなっても、dispatch
のみを使用することもできます。モジュールが増えても、createNamespacedHelpers
が後続の作業に向けた道筋を整えてくれます。