前書き
これは、本を読むのが好きだけど探すのが嫌いな僕が、適当な説明文を書いておけば誰かが勝手におすすめのものを教えてくれる「積んでけ」というサービスを作った際に学んだことを書いているものです。
はじめに
この記事はAndroidとnuxtを比較して考えた場合に、どこがなににあたりどういった処理を書くべきか?という観点で記載したものになります。
初期のフォルダ構成は以下となっているものとします。
├── components
├── pages
├── store
└── layouts
components = CustomView
componentはCustomViewにあたるものと考えます。全てのHTML要素はComponentで記載するぐらいの気概で記載していくと再利用もしやすくなりアプリとしての統一性も出てきやすいでしょう。AndroidでいうところのButtonのようなこれ以上分解できない最小単位のView単位でpartsを作成していき、そのPartsの組み合わせで使いやすい単位のCustomViewを作っています。このCustomViewは渡された情報の表示のみを行います。外部との通信などは行わずタップ等のイベントを外に受け取るための口だけを作成しておきます。
├── components
│ ├── parts
│ │ └── buttons
│ │ └── confirmButton.js
│ └── area
│ └── areaCard.js
├── pages
├── store
└── layouts
pages = Fragment + ViewModel
各種pageはFragmentとViewModelを足したようなものです。Lifecycleに応じてAPI通信などを行いデータを取得しComponentに流して表示したり、Componentからのイベントに応じてデータの保存や更新などを行います。また、PageのTemplateには直接HTMLを記載するのではなく、一度Component化してからPageが参照するようにするとカスタマイズ性が上がりそうです。ページ固有のデータを保存するのもstoreではなくpage.dataに記載したほうがスッキリすると思います。
├── components
│ ├── parts
│ │ └── buttons
│ │ └── confirmButton.js
│ └── area
│ └── areaCard.js
├── pages
│ └── area
│ └── index.js
├── store
└── layouts
store = SharedElement???
最初は全てのAPI通信等をstoreを通して行うように作成していました。pageからstoreにイベントを投げてstoreがAPI通信を行い結果を保存し、保存先を監視しているPageが変更を察知してViewに流すという作りにすると一見きれいに動いているように見えます。しかし、この方針はあまりよくありませんでした。
storeの値はアプリで共通なのでPage固有の情報を保存すると別のPageからアクセスされてしまう可能性がでてきます。これは同じPageで別の値を表示する可能性がある場合、前のPageの値が保存されている場合があり、非常にバグを生みやすそうだなと感じました。なので、storeにはアプリ全体として共通する値のみを保存する(例えば認証情報)ものとし、Page固有の情報はpage.dataに保存してAPI通信もpageに書くようにしました。このへんは好みが分かれるところなのかなと感じています。
├── components
│ ├── parts
│ │ └── buttons
│ │ └── confirmButton.js
│ └── area
│ └── areaCard.js
├── pages
│ └── area
│ └── index.js
├── store
│ └── auth.js
└── layouts
layouts = Activity
layoutはActivityと考えて良さそうですが、layoutとpageの関係性がActivityとFragmentの関係と同じか?と言われるとちょっと違います。同一layoutで動く分には再生成されないので、Activityが表示された後に中のFragmentが変わっていっていると考えることもできますが、page側でlayoutを指定するためあくまで主体はpageの方だと思います。全体的に共通するHeader / Fotterを表示する便利機能的で、ここも直接Pageと同様の共通部品のビジネスロジックを書いていくと良いのではないでしょうか。
├── components
│ ├── parts
│ │ └── buttons
│ │ └── confirmButton.js
│ └── area
│ └── areaCard.js
├── pages
│ └── area
│ └── index.js
├── layouts
│ └── authed.js
└── store
└── auth.js
終わりに
大規模開発をしていくとこの構成では不具合が出てくるのかもしれませんが、個人開発のレベルだとこんなイメージで書いていくと破綻しないように感じます。ただ、Androidでも起こるActivityが神クラス化していく問題と同じように、この書き方で進んでいくとPageが神クラス化していく予感があります。ViewModelとして処理を分割するようにnuxtでも同じ役割を担うクラスを新設すればPageの肥大化は防げるのではないかと思っています。
宣伝
もし興味があれば使ってくれると嬉しいです。
世界にはあなたやわたしがまだ出会っていないすばらしいものが無数に存在します。 あなたが知っている素晴らしいものは、だれかが探し続けているものかもしれません。 あなたが探し続けているものは、だれかがすでに素晴らしいと思って使っているものかもしれません。 「積んでけ」はだれもが気軽に軽い気持ちで自分が知っている素晴らしいものを教えあうサービスを目指しています。