CYDAS Developer's Blog

サイダス技術者ブログ

VuexとAtomic Design

f:id:kfukuyama:20190522213224p:plain

大阪からこんにちは、福山健@kenfdev)です。

フロントエンドに関わっているエンジニアであればAtomic Designというのを聞いたことがあるかもしれません。

フロントエンドの開発をしていく上で大事なことの一つに、画面の部品をどのようにComponentに分割していくかというものがあります。

きっとたくさんのフロントエンドエンジニアがこの点については毎回悩まれると思います。

そこで、どのように分割していくと良いかという指標の一つとしてAtomic Designという考え方があると僕は解釈しています。

Atomic DesignはBrad Frostさんという方が提唱したもので、英語であれば下記にて公開されていますし、本を注文することもできます。

atomicdesign.bradfrost.com

また、日本では下の書籍がReactを使って具体的にわかりやすく説明されています。(ただし、SPAフレームワークを触ったことが無いとちょっとつらいかも)

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

この記事ではAtomic Designについては詳しく見ないので、そもそもAtomic Designについて知りたい方は上の書籍や、わかりやすいブログ記事も多数あるのでそれらを先に読むことをおすすめします!

ではこの記事で何を述べるかと言うと、Vue.jsのVuexを使ったプロジェクトでAtomic Designを採用した場合に、VuexのStoreとAtomic DesignのComponentがどのようにやり取りすると良いかを紹介します。

あくまでこのやり方は1例に過ぎず、やり方は多数ありますので迷っている方の参考になればと思います!(CYDASでもやり方は日々アップデートしています!)

Atomic DesignとVuexで何に迷うのか

これは「Atomic Designだから」、という問題では無いのですが「誰がVuexを意識するのか?」という課題が常につきまとってきます。

具体的には:

  • 誰がVuex StoreからStateを受け取ることができるのか
  • 誰がVuex StoreにActionをdispatchしていいのか

という2点がポイントになってきます。ここに一定のルールを設けないと、そこら中からStateを受け取ったり、そこら中からActionをdispatchしたりしてどこで何が起きているのかかなり追いづらくなってしまいます。

イメージとしては下図のような状況です。

f:id:kfukuyama:20190521072408p:plain
フローが追いにくい関係

「Pages, Templates, OrganismsはPropsを受け取ることもあれば、Storeからstateを受け取ることもあり、eventを$emitすることもあればStoreにdispatchすることもある。」のがわかります。

これでは流れが追いにくかったり、実装するときも迷いが生じやすくなります。

Atomic DesignとVuexの良い関係

そこで、僕が今のところ良いと思っているAtomic DesignとVuexの関係は下図のようになります。

f:id:kfukuyama:20190521091719p:plain
追いやすくしたフロー

言語化すると、

  • Storeからstateを受け取るのはPagesのみ
  • Pages以外はPropsでしか入力を受け付けない
  • Storeにdispatchして良いのはPagesとTemplatesのみ
  • Pages, Templates以外はdispatchしてはいけない(イベントは$emitするのみ)

というルールになります。

StoreはPagesのみが意識すべきでは?

ここで出てきそうなのが「StoreはPagesのみが意識すべき」という意見です。

ルールとしてはわかりやすいんですけど、実際にやってみるとTemplates→Pagesにeventを$emitして、PagesからStoreにdispatchするのが冗長に思いました。

f:id:kfukuyama:20190522192314p:plain
Templates→Pagesのコピペ感がつらい

Templates→Pagesへの$emitが増えるほどPagesでもイベントハンドラが増えてしまうのです。。。(やり方はいくつかあるにせよ冗長さは避けられないと思います)

そういうわけでCYDASでは「dispatchに関してはTemplatesからやってもいいのでは?」という意見もあってTemplatesまではStoreを意識して良いルールにしています。

Pagesはいつdispatchする?

Templatesがdispatchするなら、むしろPagesはいつdispatchするのか?という疑問も出てくると思います。

基本的にOrganismsより下の層から$emitされたイベントについてはTemplatesからStoreにdispatchします。

なので、Pagesがdispatchするタイミングはmountedなどの、ページ初期化時などのタイミングくらいしか無いのかなと思っています。

TemplatesにPropsは必要なのか?

Templatesからdispatchができるなら、いっそのことstateもStoreから持ってこればいいのでは?という疑問も出てきます。

それをやってしまうともはやPagesが必要なくなると思うのですが、あくまでデータはProps経由でもらうというルールにしています。

というのも、Atomic Design(にこれも限らずですが)とStorybookを組み合わせて使うことも多いかと思います。

storybook.js.org

このStorybook上でTemplatesを表現する際に、Propsで制御できたほうがVuexのセットアップ(gettersだったりstateだったり)が必要なくなります。

標準のVue.jsで、Propsにデータを差し込むだけでいろいろなデータを流し込めるので、変に手間のかかることをせずに済むと思っています。

そういったわけで、TemplatesはPropsでデータを受け取るようにしています。

まとめ

この記事で述べているやり方はあくまで1例にすぎません!大事なのは皆が好き勝手違う書き方をしてしまわないようにルール(コーディング規約)をある程度決めておくことだと思います。

そしてやってみて、フィットしなかったらもっと良いと思う方法に変えていけば良いんだと思います(手戻りは発生してしまうのは覚悟の上で)!

参考