Vue,Fluxを使用して再利用性の高いapp設計を実現する

大きな規模のWebアプリケーション、例えばコンポーネントのが4,5階層になるようなアプリをVueのデフォルト機能を使用して制作すると起こる問題として、『データ』や『$emit』のバケツリレーがあります。

この問題を解決するために各パーツ、コンポーネントにそのコンポーネントで使用する処理を閉じ込めるという対応をすると、依存性が高くなり、再利用性が低下する原因となります。

そんな課題を解決するためにFluxを採用してみたところ、うまくいったのでその設計についてまとめます。

前提として、設計を行う上で抑えておきたい以下のポイントがあります。

  • コンポーネントには共通のAPI形式を定義し、どのコンポーネントともに連結/切り離しが可能で、依存性を失くす。
  • コンポーネントの再利用性を高める

そしてこの要件を満たすために以下を徹底しました。

  • データ更新の流れはFluxにのっとる
  • 各コンポーネントにはその中で完結する処理以外は持たせない
  • 各コンポーネントはその中で完結するデータ以外は持たせない
目次

ディレクトリ構造

まず、ディレクトリ構造から理解すると全体像が理解でき、イメージがしやすいかと思います。

プロジェクト全体を掲載すると、今回関係のないcssやWebAPI通信用のコードが入ったディレクトリなども含まれてまうので、説明に使用するもののみ記載します。

ディレクトリ構造は以下のようになっています。

js/component       → componentレベルのパーツを格納
js/project         → projectレベルのパーツを格納
js/layout          → layoutレベルのパーツを格納
js/lib             → アプリ全体で使用する関数や処理を格納

それぞれのディレクトリの役割は記載されている通りです。

componentにボタンやテキストインプットなど、使いまわせる最小のパーツ単位のコンポーネントを格納します。

そのコンポーネントを使用してフォームや検索ボックスなど、1つの機能を制作します。

コンポーネントを組み合わせて制作したパーツをプロジェクトと呼び、projectに格納します。

そのプロジェクトを複数集めて1つのページを構成します。

その際、プロジェクトを適切な箇所に配置する役目が必要ですので、プロジェクトを集めたものをレイアウトと呼び、layoutに格納します。

libフォルダはアプリ全体で使用する関数や処理をまとめ、それらを各プロジェクトやコンポーネントで再利用すると言った形です。

全体の設計

今回のメインとなるアプリ全体の設計の説明をします。

アプリ制作をする際に大切になる事がデータの更新方法ですが、現在、ほとんどの場合MVC設計を取り入れ、データのやり取りを一本化する事が主流かと思います。

そのMVC設計の中でも今回はFluxを取り入れました。

Fluxについては以下の記事にサンプルコードとともに簡単に説明していますので参考にどうぞ

[Vue]Fluxでアプリケーションを制作する

では、Fluxは知っている前提で話を進めます。

今回の設計のポイントはコンポーネントの再利用性と簡単に連結/切り離しが可能という点でした。

Fluxを使用する事により以下のようなデータ構造を取ることが可能です。

情報がその中で簡潔するパーツを1つのプロジェクトとし、プロジェクトの中に必要なコンポーネントをぶら下げ、そこで使用するデータをFluxのサイクルで回して運用します。

project-ツリー

上記コンポーネントツリーをDOMにすると以下のようになります。

<div id="root">
  <ComponentA>
    <ComponentE />
    <ComponentF />
  </ComponentA>
  <ComponentB />
  <ComponentB />
  <ComponentC>
    <ComponentG />
    <ComponentG />
  </ComponentC>
  <ComponentD />
</div>

rootがprojectのtopになり、全てのデータすべての処理を保持し、Observerへの登録などを行います。

AからGのnodeが各コンポーネントとなり、上記画像のようにツリー構造で連結し、この中でデータをFluxに従い更新します。

各コンポーネントはツリーのどの箇所からも切り離したり、どの箇所にも連結できるようにします。

各コンポーネントのデータ(状態)と処理

project-データ(状態)処理

AからGの各コンポーネントのデータ(状態)と処理はroot(project)に持たせ、コンポーネント自体は*自己完結するもの以外は何も持たない状態にします。

*例えばテキストインプットなら、フォーカスが当たった場合につけるclass名を定数で保持する場合などはコンポーネント内でそのデータを保持してもよいでしょう。

状態A=1と処理AはコンポーネントAの値、状態B=2と処理BはコンポーネントBの値と言った具合に関連しています。

ですのでコンポーネントはツリー構造ですが、状態や処理は平行で保持しているイメージです。

こうする事により、このツリー構造を作り替える事で様々なパーツを制作する事が可能です。

例えばテキストインプットとボタンコンポーネントをつなげてログインフォームプロジェクトを制作出来ます。

ログインフォームなのでパスワード入力がありますが、パスワード入力には英数字のみを受け付けるためのバリデーションが必要になるかもしれません。

バリデーション処理を各コンポーネントの中に記載しそうですが、図の『処理』の部分に外だしで定義する事で、ログインフォームで使用したテキストフィールドコンポーネントを再利用して新たに検索ボックスプロジェクトを制作することも可能となります。

Flux-layoutツリー

そして制作した各プロジェクトをさらにレイアウト内でツリー構造にしてつなげる事で1つのアプリケーションを構築する事が可能となります。

flux-layoutデータの流れ

上記図のようにデータはそれぞれのプロジェクトの中でサイクルを回しているので、各プロジェクトツリーはroot部分から簡単に切り離しが可能ですし、各コンポーネントはどこからでも連結/切り離しが可能となり、無限の拡張性を持った形で制作する事が可能となります。

Fluxのデータ更新サイクルのイメージ

Flux-データの流れ

データの更新は上記の図のようにFluxのデータ更新の流れにそって行います。

上記図の『データ』がキャプション” project-データ(状態)処理 ”の図の『状態』のA=1,B=2の部分となり、上記図の『処理』が キャプション” project-データ(状態)処理 ” の図の『処理』のA,Bの部分となります。

Fluxのデータ更新の具体的な流れ

次は具体的にユーザーアクションからコンポーネントのデータを更新するまでの流れ説明します。

例として簡単なログインフォームを取り上げてみます。

ログインフォームには以下を満たします。

  • ユーザー名、パスワード、ログインボタンの3つのパーツから構成
  • ユーザー名、パスワード入力フィールドはユーザーからのテキスト入力を受け付ける
  • パスワード入力フィールドは英数字しか受け付けない
  • ログインボタンはユーザー名とパスワードが両方入力されていなければ非活性状態となる
  • ログインボタンをクリックするとユーザー名、パスワードがconsoleに出力される

テキストフィールドやボタンのコンポーネントの細かい実装の説明は一旦おいて、このログインフォームのデータの流れを今回の設計通りに更新してみます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

プログラムちょと書ける。
いまはバリ島でスクール作っている。
プログラムちょっとできる。

目次