vuexフォームのデータをどこで管理するか問題について

はじめに

vue・vuexを利用し規模の大きいアプリケーションを開発している際、フォームのデータをvuexで管理すべきか?コンポーネントで管理すべきか?という問題をについて考えた。

vuexで管理

vuexのようなstate管理ライブラリを使っているのであれば、フォームのデータも当然vuexで管理するべきと考えられる。
すべてのstateはvuexで一元管理したい。
だが、vuexにデータをもたせることはコンポーネントのデータバインディングの機能のv-modelを活用できなくなるデメリットもある。
vuex側が厳格モードならば、フォームのデータの変更ひとつにmutations・actions書き、それはたいへん冗長だ。
その冗長性を排除するという目的のためヘルパーをつくるなどをつくり、メンテナンス性・属人性の新たな問題を生む。

コンポーネント内で管理

コンポーネント内でフォームのデータだけ管理すると、state管理が一元集中ではなくなり複雑性を生む。
vuexを利用せずに、一定規模のサービスを開発をしたことがある人ならばstate変更の複雑性を避けたいと思うだろう。

どちらも良し悪しがある。ではどうしたらいいのか。

なぜvuexが必要か?

そもそもどうして、vuexのようなステート管理ライブラリが必要なのか?ということを考え、どんな課題を解決するのかを理解する必要がある。

vueのようなコンポーネント思考で起きる問題

vueはhtmlを拡張してコンポーネントをつくり、それを組み合わせることでアプリケーション構築するライブラリだ。ロジックも状態も各コンポーネントにカプセル化することで、再利用可能なものとしている。

vuexにより廃止されたイベントシステム

以前、コンポーネントのイベント共有はbroadcast/dispatchといった仕組みが利用されていた。
broadcastやdispatchを使って他コンポーネントへイベントの通知を送ることができる。
しかし、これらの仕組みを利用すると、アプリケーションの大規模化に伴い状態管理が複雑になっていく。

状態が多くのコンポーネントに分散し、更にそれらが相互作用するようになると$broadcastを使ったコンポーネント間でのイベント通知が多用され、コンポーネント同士が密結合・複雑化し始める。
どこでいつstateが書きかえられるのか把握できなくなった。dispatchおよびbroadcastは、コンポーネント間の通信及び状態管理のVuexを支持するかたちで廃止となった。

vuexとは

vuexはStoreというグローバルな共有オブジェクトに複数のコンポーネントから使用される共通の状態・処理・イベントを管理させることで、コンポーネント同士を分離する考え方だ。
stateの変更される場所をstore内と限定し、stateを一元管理することで複雑性を軽減した。

つまりvuexは前提としてコンポーネント間でstateの受け渡しが行われ複雑化されるstate管理の問題を解決するものだ。

結論

コンポーネント間で受け渡しの必要のないデータであれば、state管理に問題がおきることは少ない。
フォームのデータが他コンポーネントで使用されるのであればstoreで管理し、コンポーネント内のみで完結するのであればコンポーネントで管理するのが最もflux系state管理ライブラリの思想に則った手法といえる。

問題の定義

問題の定義の仕方「フォームのデータはstoreで管理すべきか?」がそもそも間違いであり、一様にYesともNoとも言えない。
それはフォームのデータの在り方によって変わるからだ。
「他コンポーネントで利用されるフォームのデータはstoreで管理すべきか?」
ならばstoreで管理すべきだし、
「他コンポーネントで利用されることのないフォームのデータはstoreで管理すべきか?」
ならばコンポーネントで管理する。
正しい問題の定義が正しい回答を導く。


とはいえ、あるフォームのデータはstoreで管理され、あるフォームデータはコンポーネントで管理されるという一見、統一性のないようにみえてしまうかもしれない。
また他コンポーネントで利用されるかは仕様・コンポーネントの粒度により流動的で変更の頻度がたかい。その度フォームデータの管理場所を変えるのは無駄と感じる。
そして「storeでstateをすべて管理」という単純なルールはわかりやすい。

まとめ

良い面悪い面がある中、盲目的にならず理解と判断をもち、ご利用はご計画的に。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.