【Vue.js】Vuex + LocalStorageで入力内容をブラウザに保持する

2019/02/03

フリーランスの所得税・住民税・個人事業税・国民健康保険料計算しミューレーションで入力内容を保持するため、VuexとLocalStorageを使って実装します。

環境

  • Vue.js 2.5.17
  • Vuex 3.0.1
  • webpack 3.12

前提条件

コンポーネント毎にdataオプションで保持データを管理するのは厳しいので、Vuexの状態管理で一元管理することが前提です。その方が、ストアの管理だけに集中できますので楽ちんです。

dataオプションからVuexへの移行は配列構造を除いて難しくありませんでした。
オブジェクトの配列をVuexのストアと各コンポーネントに設置するコントロールへバインドする方法だけ模索する必要がありました。その記事はこちら。

localStorageの読み込みと保存の実装

本当はプラグインにした方がよさそうですがはじめての実装なので、Vuexのストア構造内に直接実装します。分けたくなったら分ければいいかなぁという感じです。

シミュレーション用のデータ構造として以下のようなstore構造があります。
※ getters、mutations、actionsは本当は色々処理がありますがLocalStorage保存には使用しないので省略してます。

store.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
  strict: process.env.NODE_ENV !== 'production',
  state: {
    // 収入
    income: null,
    // 月毎の収入 (オブジェクトの配列)
    incomeMonths: [
      {month: 1, value: null },
      ~
      {month: 12, value: null }
    ],
    // 経費
    expenses: null,
    // 控除額 (オブジェクトの配列)
    deductions: [],
    // 国保 家族構成 (オブジェクトの配列)
    familyStructure: familyStructure
  },
  getters: {
    ~
  },
  mutations: {
    ~
  },
  actions: {
    ~
  }
})

ここにLocalStorageへのミューテーション(mutations)とアクション(actions)を追加します。
LocalStorageへ追加する際に使用するキー文字列は「store」にします。

const store = new Vuex.Store({
  state: ~,
  getters: ~,
  mutations: {
    save(state) {
      // Json文字列に変換しLocalStorageへ保存
      localStorage.setItem('store'), JSON.stringify(state))
    },
    load(state) {
      if (localStorage.getItem('store')) {
        // LocalStorageから取得したJson文字列をパース
        const store = JSON.parse(localStorage.getItem('store'))
        // stateを置き換えます。
        this.replaceState(Object.assign(state, store))

        // ※ ちなみに以下はNGです。stateプロパティは読み取り専用なので。
        // this.state = store
      }
    }
  },
  actions: {
    doSave({commit}) {
      commit('save')
    },
    doLoad({commit}) {
      commit('load')
    }
  }
})

LocalStorageへ保存する際は、stateプロパティを渡すだけなのでとても簡単です。
LocalStorageから取得したデータでstateプロパティを置き換える際は、「replaceState(state, Object)」を使用するのがコツ。詳しくは、VuexのAPIリファレンスを参照してください。

これで準備は整いました。

画面を開いた際にLocalStorageからデータを読み込む

画面を開いた際、すでにLocalStorageにデータがある場合は読み込みしたいのでVueインスタンス生成時に仕込みます。

main.js

import Vue from 'vue'
import App from './App'
import store from '@/store.js'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store: store,
  components: { App },
  template: '<App/>',
  beforeCreate() {
    // LocalStorageからデータ読込
    this.$store.dispatch('doLoad')
  }
})

保存処理の実装

用意したアクションを呼びます。

<template>
  <button v-on:click="save()" >入力内容をブラウザに保存する</button>
</template>

<script>
export default {
  methods: {
    save: function() {
      this.$store.dispatch('doSave')
    }
  }
}
</script>

入力するたびに自動保存する

各数値などを入力した際に自動保存したいようなケースは以下のように、ミューテーションの呼び出しをフックします。

store.js

const store = new Vuex.Store({
  ~
}

store.subscribe((mutation, state) => {
  localStorage.setItem('store', JSON.stringify(state))
})

以上です。Vuexを使うとLocalStorageの取扱いも見通しが良い形で実装できますね。

参考書はこちら。