Vue3からの状態管理について
Options APIとComposition API
Vue2のclass構文のOptions APIとVue3からの関数型を意識したComposition API
optionsAPI
code:app.js
<script>
~~~~
data: () => {
return {
color: ""
}
}
methods: {
setColor(colorName) {
this.color = colorName
}
}
</script>
compositionAPI
code:app.js
<script>
~~~~
setup() {
// data
const color = ref("");
// methods
const setColor = (colorName) => {
color.value = colorName;
};
return { color, setColor };
},
</script>
従来のOptions APIだとコンポーネントを扱うのにthisが含まれているためロジックとして外部に切り出しづらかった
scriptの肥大化した単一コンポーネントファイルが出来上がる
vue3, composition APIからはsetup()でthisは使えなくなり、stateやfunctionも外部でも持てるようになった
つまりView部分とロジック部分を切り離すことができる
MVPデザインモデルにおけるViewとPresenterの分離に相当するらしいですnishiyamayudai.icon
ロジックをコンポーネント外に出す
画面ごとにstate、stateを更新するための関数をコンポーネントの外に出してやっていく
コンポーネントのロジック部分や状態をuseXXXにして分離する
サンプルコード
共有stateを持ちたいとき
ただ上記の方法だと外に出せても画面を跨いでStateを保持したいときにできない
provide/injectについて
https://v3.ja.vuejs.org/images/components_provide.png
僕らは普段バケツリレーという呼び方をしながら末端のコンポーネントにpropsやemitを渡してる
provide/inject自体はVue2.2から導入された
Vuexでもstoreで管理できるのでそこにアクセスして参照すれば末端のコンポーネント からもバケツリレーせずに持ってこれるがStoreがグローバルにアクセスできるため、治安が悪くならないようあまり多用したくない
provide/injectで深くネストされたコンポーネントに親コンポーネントからそれらを渡すことができる
ちょっと違うかもだけどlocalStrageのイメージが近いかも(指定したkeyに値を保存し受け取りたい場所で取り出す)
provideの位置をこちらで決めることができる
例えばpagesのコンポーネントにprovideを持って他の画面では使えないようにすることができるので、限定的なストアを作ることができる
provideは複数作れるので、Storeのグローバルなアクセスを避けることができる
ただしinjectしたコンポーネントは依存度が上がり再利用しにくくなるため、一部のコンポーネント専用に使うようにする
でもglobalに参照できるStoreが欲しい時もある
その場合はPagesよりさらに上位のコンポーネントにprovideを置いて全画面共通のstoreを持つこともできる(ここまでいくとVuexと同じですね)
provide/injectのサンプルコード
Vuex4について
これまでVue2のOptions APIのころは状態管理するときはVuexがよく採用されていた
Nuxtなどでも大規模プロジェクトになると標準で用意されてたから利用する人が多かった
現在でも多くのプロジェクトで Vuexが使われている
Vuex4からComposition APIに完全対応した
compositionAPI導入してもVuexは対応してなかったのでどうしても使いたい場合はその部分だけOptionsAPIにしてthis.$storeしてた人も多い気がする。
Vuex自体は広く使われてるので今後も使われると思う
Vuexのサンプルコード
まとめ
コンポーネントのロジック部分を外に出すと修正箇所が見やすくなる
provide/injectでStoreにスコープを持つことができて、バケツリレーを少なくできる
Vuexもアップデートでcomposition APIに最近対応した
所感
classコンポーネントの頃はOptionsAPIにしろデコレーターを使うにしろ誰が実装してもコンポーネントの中身は同じになるから初心者でも導入しようみたいな流れだったはず。CompositionAPIからはsetupの中身など設計方法が試されるようになったように感じる。
これは本当にそう。Composition APIの構文は(React Hooksの時と同様に)ロジックを末端に寄せさせようという力をすごく感じるし、そうなると処理を中央集権化しようとするVuexは使いたくないねという気持ちになってくるnishiyamayudai.icon
質問
provide/inject は composition api の思想で vuex の思想とは別、であってますか・・? umamichi.icon
別。本当に共通で管理したいもののみ、provide/inject で管理する、がよさそう(個人的見解) umamichi.icon
onuma.icon 個人的にはprovide/injectは単純にバケツリレーを省略するためだけに使うのが良いかなと思っています
umamichi.icon ということは、共通で管理したいものはvuexで管理し、バケツリレー省略のために provide/inject を使う、みたいなことですかね・・?
onuma.icon はい!あと基本的にこういう省略系は好きじゃないのでどうしてもって時にか僕は使わないですかね。。(あんまり無駄に機能を増やしたくないですし)
umamichi.icon なるほどなあ・・それは同意。 provide/inject もまだ発展途上感あるから今後変わりそうだしね・・文字列で管理するところとかw
nishiyamayudai.icon provide/inject 自体は以前からあって、ただ Vuex を使うとそちらでカバーできてしまうのであえて使う機会がなかったのだと思っています。要件にもよりますが、Vuex 絶対使わないみたいな制約をつけるとしたら代替案として候補に上がってくるというのが今回の話かなと!
onuma.icon 基本的にライブラリで使うためのようですね。普段使いで使われるものではなさそうです🤔
provide および inject は、主に高度なプラグインやコンポーネントのライブラリのために提供されています。一般的なアプリケーションのコードで利用することは推奨されません。
tsuzakitakehiro.iconちなみにその注意書き、Vue3になってから英語では消えたようです見たらv2の元の言語にもなかった...日本語で追加されたのか...
onuma.icon そうなんですね!知らなかった。。
単純にこの説明が2の頃に書かれてたっぽいから、3になってcomposition APIになったらここも変わるのかな?ってのが素朴な疑問でした
vee-validateのValidationObserver, ValidationProviderの関係のように、小コンポーネントがどの階層に配置されるか分からない時に無理やりprovide/injectしてデータを拾っている感じがしますね
umamichi.icon ふむふむ、めっちゃ勉強になりました。
👍 Nishiyama Yudai nishiyamayudai.icon がいいねしました on 2021/3/10
👍 tamuraryoya tamuraryoya.icon がいいねしました on 2021/3/10