ENECHANGE Developer Blog

ENECHANGE開発者ブログ

Vuexでのデータの永続化について

こんにちわ。ENECHANGEのMariMurotaniです。 今回は、Vue.jsでのデータの扱い方について説明します。 前回の前回のRails 5.2 + WebpackerでVue.jsを使ったSPAを実現で環境構築が完了している人が対象です。

1. 概要

今回はvuexでのデータ管理とvuex-persistedstateを使ったフロントエンドでのデータ永続化について説明します。 vuex-persistedstateを使うとデータはブラウザのlocalStorageを使って永続化されブラウザのリロード時もフォームの入力結果などを保持してくれるようになります。 また、デバックしやすいようにChromeのVueプラグインの事前インストールを推奨しています。

2. 前提条件

Railsにvueをインストールのチュートリアルを終了してフロントエンド開発に慣れておきましょう。

3. インストール

yarn add vuex vuex-persistedstate

4. コーディング

Vue.jsのチュートリアルを最初から学習した場合にstoreパターンを利用してアプリケーション内でデータストアの一意性を保持するようにという概念について学ぶのですが、こちらはデザインパターンの話であり実際にはvuexというデータストアライブラリを使って開発する事をお勧めします。 まず、store.jsというファイルを作成して下記のライブラリをimportします。

4.1 データストアの作成とVueインスタンスへの登録

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

js内でVueコンポーネントを生成する際にstoreに読み込んだVuex.StoreをVueオブジェクト生成時にstoreに指定します。こうすることで、生成されたVueインスタンスの中でthis.$storeという指定方法でstoreのデータを参照したり機能を呼び出したりする事ができるようになります。

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

document.addEventListener('DOMContentLoaded', () => {
  new Vue({
    el: '#app',
    store: store,
    router,
    render: (h) => h(App)
  })
})

store.jsに機能を追加していきます。

export default new Vuex.Store({
  state: {
    count: 0
  },
  getters: {
    getCounter: function(state){
      return state.count
    }
  },
  mutations: {
    increment (state) {
      console.log("mutations > increment is called")
      state.count++
    },
    assign: function(state, args){
      console.log("mutations > assign is called")
      state.count = args.amount
    }
  },
  actions: {
    increment (context) {
      console.log("action > increment is called")
      console.log(context)
      context.commit('increment')
    },
    assignValue(context,arg1) {
      console.log("assignValue")
      console.log(arg1.amount)
      console.log(context)
      context.commit({
        type: 'assign',
        amount: arg1.amount
      })
    }
  }
})

new Vuex.Store()に記載するオプションについては、 Vuex.Store コンストラクタオプションに全てのオプションが記載されています。今回は代表的な機能について確認します。

  • State データを格納しておく箱です。Vuexインスタンス作成時に指定します。

  • Getter stateに格納したデータを取り出すメソッドを定義していきます。Vuex.Store インスタンスプロパティを参照しましょう。

  • Mutation storeのデータを操作するロジックを定義していきます。

  • Action mutationで定義したメソッドを利用して変更をコミットするロジックを定義していきます。

上記のサンプルでは、stateにcounterという変数を定義して、mutationsのincrementメソッドで値を変更、actionsのincrementメソッドで実際のデータをコミットしています。

4.2 データストアの呼び出し

アクションのincrementを呼び出します。 vuexインスタンスメソッドというのが定義されておりstoreインスタンスから呼び出しが可能になっています。よく使う2つのメソッドについて紹介します。

action経由での呼び出し

store.dispatch('increment')

mutationのincrementメソッド直接呼び出し

store.commit({
  type: 'increment',
  amount: 10
})

stateのcounterの値を直接書き換える事はできるのですがstore.commitをするまで変更は適用されません。Vueインスペクタを開いて下記のサンプルを実行して、値の変化を確認しながらボタンを押してみましょう。一番右の「updateWithoutCommit」では画面の値が更新されているにも関わらず、Vuexのモニターの中身がコミットされていない事が分かります。

<template>
  <div>
    <div>
      this.$store.state.count: {{get_value_directory}}<br>
    </div>
    <div>
      get_value_via_getter: {{get_value_via_getter}}<br>
    </div>
    <button v-on:click="incrementValueViaDispatch">incrementValueViaDispatch</button>
    <button v-on:click="upateWithSpecificValue">upateWithSpecificValue</button>
    <button v-on:click="updateValueWithMutation">updateValueWithMutation</button>
    <button v-on:click="updateWithoutCommit">updateWithoutCommit</button>
  </div>
</template>
<script>
  export default {
    name: 'page_test',
    props: {

    },
    components: {

    },
    data: function () {
      return {
        isActive: false
      }
    },
    mounted: function (event) {
    },
    computed: {
      get_value_directory: function() {
        return this.$store.state.count
      },
      get_value_via_getter: function() {
        return this.$store.getters.getCounter
      }
    },
    methods: {
      incrementValueViaDispatch: function(){
        this.$store.dispatch('increment')
      },
      upateWithSpecificValue: function(){
        this.$store.dispatch({
          type: 'assignValue',
          amount: 10
        })
      },
      updateValueWithMutation: function(){
        this.$store.commit({
          type: 'assign',
          amount: 20
        })
      },
      updateWithoutCommit(){
        this.$store.state.count = 100
      }
    }
  }
</script>
<style scoped lang="scss">

</style>

4.3 データの永続化

データの永続化をするにあたってcreatePersistedStateをpluginsオブジェクトに追加する事でlocalStorageを利用したデータの永続化が実現できます。storeオブジェクト生成時にpluginsの値を指定します。

import createPersistedState from "vuex-persistedstate";

export default new Vuex.Store({
  plugins: [createPersistedState()]
})

f:id:mari-murotani:20190301190707p:plain

インスペクタでlocalStorageの中身を参照するとvuexというキーでstoreのstateのオブジェクトがリアルタイムに保存されていく状態が確認できます。