DDG - Develop a Digital Garden

develop a digital garden

Vuexの前に試したいストアパターン

Image from Gyazo

Vue.jsで複数のコンポーネントを作っていると、同じデータを別のコンポーネントで使いたくなることはありませんか?

まさに先日ちょっとした機能を実装している際に調べたので、ご紹介していきます。

Vuex

真っ先に思いついたのは、Vuex です。

Vue.jsの状態管理ライブラリとしてはデファクト的な立ち位置で、 とりあえずVuexを入れておけば大丈夫という印象があります。

ですが、今回実装していた機能はSPAではなく、既存ページに部分的にVue.jsを利用するようなモノでした。

複雑な親子コンポーネントもなく、Vuexでは機能が多すぎるので、もっとシンプルな方法は無いかなーと考えていました。

ストアパターン

Vue.jsのドキュメントを読んでいると、 ストアパターンという状態管理の実装方法が紹介されていました。

状態管理 — Vue.js

今回は、兄弟コンポーネントに共通して利用しているデータがあり、それぞれのコンポーネントで そのデータの変更をトリガーにして、APIからデータを取得したりするような要件でした。

複雑な状態操作は行っておらず、データを変更すると処理が1つ実行される程度です。

なので、データの状態だけを管理できればよく、データの操作を統一するような実装は不要でした。

公式ドキュメントでも紹介されていた 単純なストアパターン でのデータ共有で問題なく実装が完了し、リリースできました。

実装例

簡単な例で ストアパターンを使ってみます。 以下のような例題があったとして進めていきます。

AさんとBさんはとても仲良しで、いつも同じ色の服をおそろいで着ています。
3種類の色の中から、どれを選んでもAさんとBさんが同じ色の服を着ているようにしてください。

イメージとしては、こんな感じです。

ストアパターンを導入する前は、このようなコードでした。

<body>
  <main>
   <section id="a">
     <h2>Aさん</h2>
     <ul>
       <li v-for="c in colors">
         <label>
           <input type="radio" name="color-a" v-model="color" v-bind:value="c">
           {{ c }}
         </label>
       </li>
     </ul>
   </section>
   <section id="b">
     <h2>Bさん</h2>
     <ul>
       <li v-for="c in colors">
         <label>
           <input type="radio" name="color-b" v-model="color" v-bind:value="c">
           {{ c }}
         </label>
       </li>
     </ul>
   </section>
  </main>
 <script>
   new Vue({
     el: '#a',
     data: {
       color: '',
       colors: [
         'オレンジ',
         'ピンク',
         'ホワイト',
       ],
     },
   });
   new Vue({
     el: '#b',
     data: {
       color: '',
       colors: [
         'オレンジ',
         'ピンク',
         'ホワイト',
       ],
     },
   });
 </script>
</body>

AさんコンポーネントとBさんコンポーネントがあり、それぞれに色の状態を持っています。

Vue.jsでは兄弟コンポーネント間でのデータ共有はサポートされていないため、Vuexやストアパターンを利用する必要があります。

ストアパターン実装後のコードです。 HTMLに変更は無いのでJavaScriptだけを載せています。

<script>
  // 状態を管理するためのオブジェクト
  const store = {
    color: '',
    colors: [
      'オレンジ',
      'ピンク',
      'ホワイト',
    ],
  };
  new Vue({
    el: '#a',
    // AさんとBさんで同じオブジェクトを利用する
    data: store,
  });
  new Vue({
    el: '#b',
    // AさんとBさんで同じオブジェクトを利用する
    data: store,
  });
</script>

store というオブジェクトを2つのコンポーネントで使うようにすることで、コンポーネント間で状態を共有できます。

まとめ

単純にデータを共有したいだけであれば今回紹介した ストアパターン で十分ではないでしょうか?

ストアパターンで実装した後に複雑になってきた場合に、やっと Vuex を導入するか検討する、という流れでもいいのではないかと思います。

とりあえずライブラリを導入するのではなく、必要最小限の機能を実装し、必要になってからライブラリの導入を検討する方が、実装スキルも身につくのではないでしょうか。