【Vue.js】store パターンでシンプルな状態管理を実装する。


はじめに

Vue.js初心者が書いた記事です。
そのためつっこみどころがたくさんあるかと思いますが、その際はご教授していただけると幸いです。

この記事では、Vue.jsのチュートリアル | 状態管理を自分なりに噛み砕いてまとめたものになります。
また、今回書いたコードはGitHubにあげてます。

storeパターンでシンプルな状態管理を実装する。

状態管理
上記サイトの項目「シンプルな上端管理をゼロから作る」で、コンポーネント間で共通の状態を保持しているときに、
その状態を各コンポーネントまたは、そのサブコンポーネントからthis.$root.$data等を通じてアクセスし変更していると、どこで状態が変更されたのかを把握しずらくなり、デバッグが大変になってしまう。

そんな時は、storeパターンを利用することでこの問題を解決することができる。

下記は参考サイトのサンプルコードを検証するために、自分なりに変更を加えたコードです。(コピペでそのまま使えるように全て載せています。)

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vuex</title>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
</head>

<body>
  <div id="app1">
    {{ this.$root.$data.sharedState }}
    <button v-on:click="setMessageAction">setMessageAction</button>
    <button v-on:click="clearMessageAction">clearMessageAction</button>
  </div>

  <div id="app2">
    {{ this.$root.$data.sharedState }}
    <button v-on:click="setMessageAction">setMessageAction</button>
    <button v-on:click="clearMessageAction">clearMessageAction</button>
  </div>

  <script>
    /* storeパターン
    状態管理を中央集権的にすることで、
    どういった種類の状態変化が起こりうるか、
    あるいはそれがどうやってトリガされているか、
    が分かりやすくなる.
    */
    var store = {
      debug: true,
      state: {
        message: 'Hello!'
      },
      setMessageAction(newValue) {
        if (this.debug) console.log('setMessageAction triggered with', newValue)
        this.state.message = newValue
      },
      clearMessageAction() {
        if (this.debug) console.log('clearMessageAction triggered')
        this.state.message = ''
      }
    }

    const vmA = new Vue({
      el: app1,
      data: {
        sharedState: store.state
      },
      methods: {
        setMessageAction: function () {
          store.setMessageAction('newValue from app1')
        },
        clearMessageAction: function () {
          store.clearMessageAction()
        }
      }
    })

    const vmB = new Vue({
      el: app2,
      data: {
        sharedState: store.state
      },
      methods: {
        setMessageAction: function () {
          store.setMessageAction('newValue from app2')
        },
        clearMessageAction: function () {
          store.clearMessageAction()
        }
      }
    })
  </script>

  <style>
  </style>

</body>

</html>

ここで大切なのは、状態(state.message)を変更するactionは全てstore自身が持っているということ。
下記は参考サイトより

このように状態管理を中央集権的にすることで、どういった種類の状態変化が起こりうるか、
あるいはそれがどうやってトリガされているか、が分かりやすくなります。
これなら何か良くないことが起きても、バグが起きるに至ったまでのログを見ることもできます。

まとめ

コンポーネントでは直接storeの持つ状態を変更することはせずに、
代わりにstoreに定義されているアクションを呼び出し状態を変更するようにする。

最後まで読んでいただきありがとうございました。