Nuxt.jsにおいてStore(ストア)を利用すると、データの状態管理をおこなうVuexによってコンポーネント間のデータの受け渡しを一元化できます。本記事ではそのStoreとvuex-persistedstateモジュールを利用してデータをLocal Storage(もしくはSession Storage)に保存してみます。
Storeにはクラシックモードとモジュールモードがありますが、本記事ではモジュールモードによる記述で説明していきます。2つのモードの違いについては公式サイトを参照して下さい。
Nuxt.jsによるプロジェクトの作成は下記ページをご覧下さい。
Nuxt.js入門 [$route.params][layouts]
プロジェクト内のディレクトリを確認します。Storeによる機能は、主に「store」ディレクトリ内にファイルを追加していくことで利用できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ tree -L 1 . ├── README.md ├── assets ├── components ├── layouts ├── middleware ├── node_modules ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── plugins ├── static └── store |
まずはHello Worldから。storeディレクトリ内にindex.jsファイルを作成し、下記のように編集します。
store/index.js
1 2 3 |
export const state = () => ({ message: 'Hello World' }) |
stateのmessageという値に対して、Hello Worldという文字列を設定しています。
次にページコンポーネントを作成します。pagesディレクトリ内にtest.vueを作成し、下記のように編集します。
pages/test.vue
1 2 3 4 5 6 7 8 9 |
<template> <div> <p>{{ $store.state.message }}</p> </div> </template> <script> export default {}; </script> |
$storeは、storeに収められているオブジェクトです。
以上で http://localhost:3000/test にて Hello World と表示されるのが確認できます。
mutationsによるstateの変更
次にご多分に漏れずカウンター機能を追加してみます。引き続き、store/index.jsを下記のように編集します。
store/index.js
1 2 3 4 5 6 7 8 9 10 |
export const state = () => ({ message: 'Hello World', count: 0 }) export const mutations = { increment(state) { state.count += 2 } } |
stateの値(上記ではmessageやcount)を変更するには、mutationsを利用します。本記事では説明しませんが、他にもactionsというmutations自体の処理をおこなう機能もあります。下記関連ページをご覧下さい。
関連ページ
Vue CLI 3 ではじめるVue RouterとVuex入門
pages/test.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<template> <div> <p>{{ $store.state.message }}</p> <button @click="counter">ボタン</button> <p>{{ $store.state.count }}</p> </div> </template> <script> export default { methods: { counter() { this.$store.commit("increment"); } } }; </script> |
14行目
mutationsの処理を呼び出すにはcommitを利用します。
storeのnamespace(名前空間)
仮にstoreディレクトリ内に、testディレクトリを作成してその中にsample.jsを追加します。
store/test/sample.js
1 2 3 4 5 6 7 8 9 10 |
export const state = () => ({ message: 'Good evening', count: 10 }) export const mutations = { increment(state) { state.count += 4 } } |
ページコンポーネント側では下記のようにして呼び出すことができます。
pages/test2.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<template> <div> <p>{{ $store.state.test.sample.message }}</p> <button @click="counter">ボタン</button> <p>{{ $store.state.test.sample.count }}</p> </div> </template> <script> export default { methods: { counter() { this.$store.commit("test/sample/increment"); } } }; </script> |
vuex-persistedstate でデータをLocal Storageに保存する
上述までの説明では画面をリロードしたり閉じたりするとcountの数値は初期化されてしまいますが、vuex-persistedstate モジュールを利用するとWeb StorageであるLocal Storageにデータを保存することができます(デフォルト設定)。
vuex-persistedstate をインストールします。
1 |
npm install vuex-persistedstate |
次にNuxt.jsのプロジェクト内のpluginsディレクトリ内にlocalStorage.jsファイルを作成し、下記のように編集します。
plugins/localStorage.js
1 2 3 4 5 6 7 |
import createPersistedState from 'vuex-persistedstate' export default ({ store }) => { window.onNuxtReady(() => { createPersistedState({})(store) }) } |
最後に nuxt.config.js ファイルのplugins項目に上記で作成したファイルを設定します。
1 2 3 |
plugins: [ { src: '~/plugins/localStorage.js', ssr: false } ], |
以上でstoreに設定したすべてのstateがLocal Storageに保存されるようになります。
keyに名前を設定するとLocal StorageのKeyとして使用されます。デベロッパーツール等でLocal StorageのKeyを確認できます。デフォルトではvuexと設定されています。
plugins/localStorage.js
1 2 3 4 5 6 7 8 9 10 |
import createPersistedState from 'vuex-persistedstate' export default ({ store }) => { window.onNuxtReady(() => { createPersistedState({ key: 'my-key' })(store) }) } |
特定のstateの値だけを保存することもできます。この説明のためにmessageも編集できるようにします。
store/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 |
export const state = () => ({ message: 'Hello World', count: 0 }) export const mutations = { increment(state) { state.count += 2 }, changMessage(state, message) { state.message = message } } |
changMessageに対して引数を受け取るようにします。
pages/test.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<template> <div> <button @click="changMessage">ボタン</button> <input type="text" v-model="message" /> <p>{{ $store.state.message }}</p> <button @click="counter">ボタン</button> <p>{{ $store.state.count }}</p> </div> </template> <script> export default { data() { return { message: "" }; }, methods: { counter() { this.$store.commit("increment"); }, changMessage() { this.$store.commit("changMessage", this.message); } } }; </script> |
4行目
フォームを用意し、changMessage関数(23~25行目)を実行することによって、stateのmessageの値を変更できるようにしています。
上述までの状態だとstateにおけるすべての値(messageおよびcount)がLocal Storageに保存されますが、もしmessageだけを保存したい場合は、pathsにその名前を指定します。
store/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import createPersistedState from 'vuex-persistedstate' export default ({ store }) => { window.onNuxtReady(() => { createPersistedState({ key: 'my-key', paths: [ "message" ] })(store) }) } |
Session Storageへの保存
同じくWebStorageであるSession Storageを利用したい場合は「storage: window.sessionStorage」を設定します。Session Storageを利用した場合は、画面(ブラウザ)自体を閉じるとデータが失われます。
plugins/localStorage.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import createPersistedState from 'vuex-persistedstate' export default ({ store }) => { window.onNuxtReady(() => { createPersistedState({ key: 'my-key', paths: [ "message" ], storage: window.sessionStorage })(store) }) } |
js-cookieによるCookieへの保存
上述までの説明で実際に実装してみると、画面のリロード(reload)時に一瞬データの初期値(messageだとHello World)が表示されてしまいます(Chrom・Firefox)。これはvuex-persistedstate自体がSSR(Server Side Rendering)による処理の後にクライアント側で実行されるからです。本記事ではjs-cookieモジュールを利用することによってCookieにデータをもたせることで解決してみます。
js-cookieをインストールします。
1 |
npm install js-cookie |
次にpluginsディレクトリ内にcookie-storage.jsファイルを作成し、下記のように編集します。pathsにcountを指定することにより、countだけCookieに保存しています。
plugins/cookie-storage.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import createPersistedState from 'vuex-persistedstate' import * as Cookies from 'js-cookie' import cookie from 'cookie' export default ({ store, req, isDev }) => { createPersistedState({ key: 'my-key', paths: [ "count" ], storage: { getItem: (key) => process.client ? Cookies.getJSON(key) : cookie.parse(req.headers.cookie || '')[key], setItem: (key, value) => Cookies.set(key, value, { expires: 365, secure: !isDev }), removeItem: (key) => Cookies.remove(key) } })(store) } |
作成したcookie-storage.js をplugins項目に設定します。
plugins/cookie-storage.js
1 2 3 4 |
plugins: [ { src: '~/plugins/localStorage.js', ssr: false }, { src: '~/plugins/cookie-storage.js' } ], |
参照ページ
Nuxt.js で SSR 時にも永続化された store の値を使う