Vue.js, React はコンポーネントベースで web ページの画面を作れる JavaScript ライブラリです。時として巨大で複雑なページの管理をする必要があります。これらのライブラリで解決しなければならない課題として、ある条件下でこのコンポーネントAの中のボタンとコンポーネントBはこうなって、またある条件下でコンポーネントB中のlabelとコンポーネントCはこうなって……という複数のコンポーネントにまたがる複雑な条件と処理が現れる時があります。そして、フロントエンドということは大体フォームが現れ、複雑な条件の真偽がユーザの入力によって変わる時がよくあります。これによってどういうことが起こるかというと極端な場合次が起こります。
- コンポーネントA中の入力によって、ある条件の真偽が変わって、コンポーネントA、B、Cの表示が変わる
- コンポーネントB中の入力によって、ある条件の真偽が変わって、コンポーネントA、B、Cの表示が変わる
- コンポーネントC中の入力によって、ある条件の真偽が変わって、コンポーネントA、B、Cの表示が変わる
この条件の真偽を判定する if を表示箇所であるコンポーネントの内部に書くのは後々苦労するパターンです。そのようにした場合、各コンポーネントは各コンポーネント全てのことを知る必要があります。この知る、というのは大体 props で渡す情報を増やす、ということです。そのようにした場合、コンポーネントABCが密接に絡んで再利用が困難になり、その上、条件式が各コンポーネントに散らばって変更の漏れが起きやすくなります。
この危険な状態を避けるためには条件分岐の処理を書く場所を各コンポーネントの親にするのが有効です。これを図示すると次です。
この方法を使うと処理が一極化されある条件で何がどう変わるのかがわかりやすくなります。特に強力なのが条件式の使いまわしがあった場合で、そういった時は大体でいい感じにまとまります。
逆にこの方法を使うときの注意点として神コンポーネント(コンポーネントの代わりにクラス等としても同様)が生まれやすい点です。この方法は元々複雑な仕様に必要な全てを知るコンポーネントを唯一つにしているだけでもあり、そのコンポーネントは何でもかんでもできるようになります。できるから、といって処理を詰め込んでいくとあっという間にコードが肥大化して読み解くのに恐ろしく労力のかかるコンポーネントになります。なるべく子コンポーネントで処理できることは子に任せておいた方が良いです。
親も子も肥えてきていてどうにもならない時はコンポーネントとは次図の様に別の外部に処理を置くのが良いです。
クラスと書きましたが React の場合は hook になるでしょうし、Vue.js でも外部でメソッドとなる関数だけ書き出しておいて、次の様にコンポーネントには定義を置くだけ、というのも良いです。
// mediator.js const mediator = () => {/*処理実態*/}; // hoge.vue methods: { mediator. // ↓には直書きメソッド群 }
このコードの設計パターンは Mediator パターンが近いです、Mediator パターンでググるとまとめてホゲホゲする処理のいい感じのコードが色々でてきます。