昨日に続いて Composition API でロジックを切り離すことを考える
やっていたタスクで色々悩んだり理解不足を痛感したことをここ数日投稿していたんだけど、ほんの少しだけ分かってきたのでこの数日間の内容と被ることも多いかもしれないがメモしておく。
ビューとロジックを分離する
そもそも Composition API を使って切り出すロジックは、ステートレスかステートフルかは関係なく、「コンポーネントではロジック置き場に置いてあるロジックをsetup
内で呼び出して return するだけ」という状態を作り出すことを目的にする。
こうすることでビューとロジックという責務を分離することができて見通しがよくなるし、ロジックだけをテストすることが容易になる。
コンポーネントでは UI 表示に集中し、そこで利用するための値を、reactive
やref
、computed
などを駆使して返すようにする。
ロジック部分
ロジックとして切り出した部分はhooks
とかusecases
とか呼ばれることが多いっぽく、関数名はuseXxx
のように use をつけることが慣習になっているっぽい。
リアクティブな変数(=state)、リアクティブに加工された値(=computed)、様々な処理を行う関数を定義する。これらをuseXxx
内で return することで、呼び出し側で利用できるようにする。
useXxx
を export し、利用する側でuseXxx
内の変数や関数を呼び出す。
定義箇所によって global か local かが決まる。
export する関数内で定義した変数や関数(JavaScript なので関数も変数に格納するけど)は、呼び出し側でuseXxx
を実行することで、呼び出し側のコンポーネントで local な値として持つ。
そのため、別のコンポーネントでuseXxx
を実行しても state や computed が共有されることはなく、各コンポーネントで独立した値を持つ。
そして、export するuseXxx
の外で定義した変数は global なスコープを持ち、複数箇所で呼ばれた場合は共有の state を持つ。
つまり、Options API で使われていた data や computed、methods を、useXxx
の内部スコープで定義するか外部スコープで定義するかで local state か global state かを分けることができる。
その他
闇雲に global state をバチバチ定義すると複数箇所から書き換えられることが発生しバグが起きやすくなることが予想されるため、global state として定義する際はreadonly
にするといいとのこと。たしかに。
ここ最近で苦労しているのは、Options API で定義されたコンポーネントでuseXxx
を使う場合にどうするかについて。
Composition API のsetup
は、Options API のbeforeCreate
およびcreated
を内包している(表現があっているのか分からない)ので、Options API ではcreated
内部でuseXxx
を呼び出し、this
でコンポーネントに bind するというのが現状最も分かりやすく誰が見ても理解しやすい状態なのではないかという話を今日仕事でした。
useXxx
を呼び出すまで data も computed も methods も空ということになるので、空の関数this.func() {}
のようなものを methods に定義し、created
でthis.func = func
のような感じにするしかない……?
Options API を Composition API に書き換えればそれが最適解なんだけれども、そう理想通りにもいかないのでどうすればいいか悩む。