前提
バージョン: Nuxt 2.15, Vue 2.6
さて、まずはVuexの利点について
Vueの良いところは、画面の部品をコンポーネントとして(HTML, JavaScript, CSSを)クローズにできるところだと思っています。
しかし、コンポーネント間のデータのやり取りはpropsと$emitを使用して行いますが、受け渡すものが増えると非常に煩雑になります。
そこで、Vuexが登場します。
コンポーネント間のVuex
Vuexを利用することで、コンポーネント間での値の受け渡しをpropsや$emitを使わず行うことができます。
しかし、ブラウザに記憶することはできません。画面をリロードすると空っぽになります。
永続化したVuex
そこで、vuex-persistedstateなどのライブラリを入れることで、永続化することができます。
yarn add vuex-persistedstate
永続化したものは画面をリロードしてもなくなりません。
一部を永続化する例
ここで例として、Vuexに保持するものに以下の2つの情報を想定します。
- コンポーネント間で利用できればよい画面情報
page
(永続化不要) - 画面をリロードしても保持してほしいログインユーザー情報
userInfo
(永続化)
Nuxtではstoreを以下のように定義します。
(後述しますが「クラシックモード」の書き方です)
export const state = () => ({
page: null,
persistedUserInfo: {},
});
export const getters = {
page: (state) => state.page,
persistedUserInfo: (state) => state.persistedUserInfo,
}
export const mutations = {
updatePage(state, page) { state.page = page },
updatePersistedUserInfo(state, persistedUserInfo) { state.persistedUserInfo = persistedUserInfo },
}
export const actions = {
(略)
}
userInfo
は永続化したいので、接頭辞"persisted"を付けています。見た目でも区別したいので。
さて、この時点ではまだstoreを定義しただけなので、永続化する対象を指定します。
import createPersistedState from 'vuex-persistedstate'
export default ({store}) => {
createPersistedState({
key: 'my-persisted-stete-key', // (keyは他と被らなければ何でもよい)
paths: ['persistedUserInfo'] // ← 永続化したいオブジェクトを指定
})(store)
}
さらに上のpluginを読み込む指定をします。
plugins: [
{ src: '~/plugins/persistedState.js' },
],
これで、persistedUserInfo
が永続化されるようになり、画面リロードしても消えなくなりました。
モジュールモードにして追加の手間を省く
しかし、永続化したいオブジェクトが増えるたびに、永続化の対象を指定していかなければならず、手間&漏れ発生で無駄なデバッグに突入!の可能性があります。
上記の store/index.js
は「クラシックモード」の書き方でした。
他にも「モジュールモード」があり、いくつかのオブジェクトごとにファイルを分けることができます。
そこで、store/index.js
の内容を以下2つのファイルに分けることにします。(再掲)
- コンポーネント間で利用できればよい画面情報
page
(永続化不要) - 画面をリロードしても保持してほしいログインユーザー情報
userInfo
(永続化)
それぞれ、store/component.js
, store/persisted.js
というファイル名にします。
export const state = () => ({
page: null
})
export const getters = {
page: state => state.page
}
export const mutations = {
updatePage(state, page) {
state.page = page;
},
}
export const state = () => ({
userInfo: {}
})
export const getters = {
userInfo: state => state.userInfo
}
export const mutations = {
updateUserInfo(state, userInfo) {
state.userInfo = userInfo;
},
}
上記を配置し、store/index.js
を削除しておけば、「モジュールモード」として動作します。
永続化の指定を以下のように変更します。
import createPersistedState from 'vuex-persistedstate'
export default ({store}) => {
createPersistedState({
key: 'my-persisted-stete-key',
paths: ['persisted'] // ← 変更箇所(対象のオブジェクトでなく、ファイル名を指定)
})(store)
}
これで、store/persisted.js
に加えられたオブジェクトは永続化の対象になるようになりました
加えて、userInfo
もpersistedUserInfo
のように無駄な接頭辞がなくても区別できるようになりましたね
使う側からは、以下のように記述します。
// 永続化されたuserInfoのnameを呼び出す
this.$store.state.persisted.userInfo.name
// 非映像化のpageをnullで更新する
this.$store.commit('component/updatePage', null);
参考になれば幸いです。
追記
しかし、vuex-persistedstateはいつのまにかdeprecatedになっているんだが...