[6/8 12時頃追記]
Vueは死んでないし殺すつもりもないし私はVueが大好きだ、誤解しないでほしい
Vue3でOptions APIは消えてないし今後消えていく方向のAPIでもないし挫折した人もこっちつかって再挑戦してほしい
[6/8 11時頃追記]
「俺はComposition API使えてるぞ!」「便利じゃん!何をいってるんだこいつは!」
あなたはすごい、でもVueを挫折した人の話を聞くに、Composition APIが「アタリマエでしょ?」の雰囲気の前にうまく馴染めず散っていったという話で、Composition API自体は好きです
Vue3の衰退を招いたのは<script setup>
かもしれないCompositionAPIという考察
ほとんど肌感であり、根拠のない妄言だと思ってもらって構わないのだが、Vue3のリリース以降Vueが流行から離れつつあり、その原因は<script setup>
とcompotision APIにあるのではないかと考えるに至った。
その辺りを書き綴っていく
お前は誰なのか
Vue2系に魅せられて以来ずっとVueを仕事にしている。Nuxtも触ったし、Nuxt3にマイグレーションするプロジェクトに従事している。
今もVueが大好きだし、Reactはほぼ(意図的に)触ってないし今後もVueを仕事にするだろう
CompositionAPIとは
Vue3を設計するにあたり、「よりTypeScriptフレンドリーな」構文としてプロパティデコレータスタイルのRFCに変わって提唱されたRFCであり、実際に実装されたAPIでもある。
Options API に setup(props, context) { } という関数を渡すと、その中は Pure なJavaScriptであり this がコンポーネントを刺さず、かわりにsetup関数の引数からpropsやその他の項目にアクセスできる。これによって型が綺麗になったねやったね!
やったか? 型が綺麗になっただけでできること増えてないぞ?
「Compotision APIは上位互換の全く新しいAPI」という誤解
「Composition API使わないのは時代遅れ!!!ダサい!!!」みたいな感覚と実際の使いにくさが幾人もの初学者を葬り、Vue2からVue3へアップグレードを試みた者を葬ったという肌感がある
Composition API変わりすぎ!!!それぐらいならReactいくぞ!!!!って人が実際結構いるのではないかと感じているのだけど、それは悲しい誤解で、 Options APIを使い続けるので何も問題なかったのに……と私は思っている。そしてVue3でもOptions APIはそのまま使うことができる。
Composition APIは選択肢の一つであって、Options APIをメインに据えてもいいのだ
<script setup>
と初期セットアップ
<script setup>
とはマクロである
内部に書かれたものを setup関数の中身のようなものとしてよしなにやってくれる
<script setup>
import { ref, onMounted } from 'vue'
// リアクティブな状態
const count = ref(0)
// 状態を変更し更新トリガーする関数
function increment() {
count.value++
}
// ライフサイクルフック
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
上記のコードはだいたい以下のようになる
<script>
import { ref, onMounted } from 'vue'
export default {
setup(){
// リアクティブな状態
const count = ref(0)
// 状態を変更し更新トリガーする関数
function increment() {
count.value++
}
// ライフサイクルフック
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
return {
increment,
count
}
}
}
</script>
最終的にコンパイラによってマージされる
<script>
export default {
data(){
return { count: 0 }
},
methods: {
increment() {
this.count++
},
mounted(){
console.log(`The initial count is ${this.count}.`)
}
}
</script>
<script setup>
の功罪
公式のスキャフォルドでいきなり出てくるな!
公式チュートリアルではOptions APIをベースに話が始まる。
ところが、 クイックスタートの> npm init vue@latest
を実行すると、App.vue が <script setup>
で作成されてしまう。
こうなると、Options APIのドキュメントはすべて意味をなさず、初学者の心をへし折ったのではないだろうか。
一癖も二癖もある ref と reactive
setup関数内ではリアクティブなデータは ref() または reactive() でラップして明示的にリアクティブにしなければならない。
そうでなければリアクティブな監視を行わないため、パフォーマンス向上につながる。
理屈はわかるのだが、 const hoge = ref("foo") としてつくると、 hoge.value = "piyo" というように、 .value というアクセサを使わないと書き込みができない。
const state = reactive({hoge: "foo"}) とすると、 state.hoge = "piyo" ができたかな。
なんか挙動に一貫性がない。そもそも2つあるのがよくわからない。
挙げ句スプレッド演算子を使うとunwrapされたりするし。
OptionsAPIのdata() メソッドがまとめてよしなにしてくれるのと比べるとどうも罠が多いような気がする
というかこの辺で詰まって初心者からVue3マイグレーションを試みた人たちを薙ぎ払っていったのではないか
Composition API と Options APIはテンプレートコンパイラ的には同じ
setup関数に書いてあることは、 beforeMountedライフサイクルの前で実行され、適切にOptions APIにマージされる。
TypeScriptの場合型定義上も問題ない。
あなた(筆者)はCompotision APIは使わないのか?
<script setup>
にはあまり魅力を感じないが、 setup() を用いたComposition APIを部分的に採用することがある。
先述の通り、適切にマージされるので、基本的にOptions APIで書いて、 VueUseを使いたいのでそこだけ setup 関数の中に書いておくみたいなことが可能である。
備考:
setup 関数の中にあるものは OptionsAPIから参照できるが、OptionsAPIの中にあるものはsetup関数の中から参照できない
結論
せっかく「わかりやすいVue」という路線で人を集めていたのに、script setupの登場で台無しになってしまった感がある。
そして数多のVueを志した人たちの首を刈り取ったのではないか。
Evanも言っていたではないか、「Composition APIは複雑なコンポーネントを整頓するのに役立てるAPIである一方で、考えなしに使うと余計な混乱を招く」「Vue3のOptions APIで満足しきれなかった人のためのComposition APIなのだ」と……出典がどこなのか全くわからないし記憶を捏造したかもしれないが
かっこいいからとかじゃなくて愚直にOptions APIを使うのはいいぞ。