Vue 3が広まるとともに、構文もOptions APIではなく、Composition APIが用いられるようになってきました。TypeScriptとの相性も高まっています(「Composition API とともに TypeScript を使用する」参照)。さらに加わったのが、単一ファイルコンポーネント(SFC)の<script setup>
構文です。
<script setup>
は単一ファイルコンポーネント(SFC)内で Composition APIを使用するコンパイル時のシンタックスシュガー(糖衣構文)です。SFCとComposition APIの両方を使うならば、おすすめの構文です。
(「SFC<script setup>
」)
そこで少し前に書いたのが、新構文で公式サイト作例のTodoMVCをつくる全9回のチュートリアル解説です。本稿はその中から、新構文やVue 3で変わった点を拾い出してご紹介します。記事の順番に沿ったピックアップですので、体系的でも網羅的でもありません。それでもお役に立てばということでご説明します。
まず全体として、テンプレートのコンポーネントタグにはパスカルケースが強く推奨されるようになったことにご注意ください。
ケバブケースの
<my-component>
も同じようにテンプレートで動作します。しかし、一貫性を保つために、パスカルケースのコンポーネントタグを強く推奨します。これはネイティブのカスタム要素と区別するのにも役立ちます。
(「コンポーネントの使用」)
01 リスト項目の表示と追加
初回の「TodoMVC 01 リスト項目の表示と追加」は基礎的な操作を扱いましたので、項目数が比較的多いです。具体的な使い方やコード例は、チュートリアル記事をご覧ください。
Vueのひな形プロジェクトはViteを使ってつくる
Vueのひな形プロジェクトをつくる公式ツールとして、これまではVue CLIが使われてきました。けれど、現在はメンテナンスモードとなっており、Vite(ヴィット: フランス語で素早いの意)を用いることが推奨されています。
npm init vue@latest
Vue CLIは、Vueのための公式のwebpackベースのツールチェーンです。現在はメンテナンスモードで、特定のwebpackのみの機能に依存していない限り、新しいプロジェクトはViteで始めることを推奨します。ほとんどの場合においてViteは優れた開発経験を提供します。
(「Vue CLI」)
コンポーネントのリアクティブな値はref
オブジェクトで定める
コンポーネントのリアクティブな値(ref
オブジェクト)を定めるのはref()
メソッドです(「ref」参照)。ref
オブジェクトのTypeScriptによる型づけは、メソッドの引数に渡した初期値から推論されます。値が単純なプリミティブでなくオブジェクトや複雑な型の場合には、ref()
の呼び出し時に型引数を用いるとよいでしょう(「ref()の型付け」)。
なお、ref
オブジェクトに収められた値を参照するとき、<script>
ブロック内ではvalue
プロパティから取り出さなければなりません。けれど、<template>
は自動的にvalue
プロパティ値にアクセスします。したがって、<template>
内ではref
オブジェクトのvalue
プロパティは参照しないことにご注意ください(「テンプレートでの使用」)。
親コンポーネントへのイベントの送信にはdefineEmits()
を用いる
親コンポーネントへのイベントの送信(emit
)を定めるのは、defineEmits()
です。「defineEmits
は、<script setup>
内でのみ使用可能なコンパイラーマクロです。インポートする必要はなく、<script setup>
が処理されるときにコンパイルされます」(「defineProps() & defineEmits()」)。defineEmits()
の宣言に渡すのは、リテラルの型引数です(「TypeScriptのみの機能」)。戻り値は送信(emit
)するための関数で、引数オブジェクトにイベントとデータを収めて渡せば、親コンポーネントが受け取ります。
Event
型のtarget
プロパティにはvalue
プロパティが備わっていない
<input>
要素のイベントハンドラでは、引数のイベントの型づけはEvent
です。ところが、この場合のtarget
プロパティの型はEventTarget
で、value
プロパティが備わっていません。そのため、instanceof
演算子により、target
が<input>
要素(HTMLInputElement
型)であることを限定します。こうして、value
プロパティ値の読み書きができるようになるのです。
親コンポーネントから受け取るプロパティはdefineProps()
で型宣言する
親コンポーネントから渡されたプロパティを受け取るには、子コンポーネントが型を宣言しておかなければなりません。そのときに用いるのは、defineProps()
です。構文はdefineEmits()
と似ていて、<script setup>
構文でのみ使えるコンパイラーマクロです(「defineProps() & defineEmits()」)。import
は要りません。リテラルの型引数を渡してください(「TypeScriptのみの機能」)。<script setup>
が処理されるときにコンパイルされます。
02 リスト項目の削除とスタイル変更
「TodoMVC 02 リスト項目の削除とスタイル変更」からご紹介する項目はひとつでした。
親から受け取ったプロパティは<script setup>
ブロックからdefineProps()
関数の戻り値で参照する
親コンポーネントから受け取ったプロパティを<script setup>
ブロックから参照するとき用いるのが、defineProps()
関数の戻り値です。各値は戻り値オブジェクトのプロパティとして取り出せます。
03 算出プロパティとデータのローカルへの保存
「TodoMVC 03 算出プロパティとデータのローカルへの保存」からは、3つご説明します。
算出プロパティcomputed()
を使う
リアクティブなデータの含まれるロジックから、結果を導いて返すのが「算出プロパティ」です。関数computed()
を用い、算出されたref
オブジェクトが返されます。引数はgetter関数です。computed()
の型づけは戻り値から推論されますので、通常は気にしなくてかまいせん。算出プロパティは、自動的にリアクティブな依存関係を追跡します。
Vue 3ではfiltersがサポートされない
Vue 3ではfiltersはサポートされません(「3.x での更新」)。代わりに、算出プロパティを用いることが推奨されています。
データの変更をリアクティブに追跡するwatchEffect()
(ウォッチャー)
データの変更をリアクティブに追跡するのがwatchEffect()
です。watchEffect()
の引数には実行するエフェクト関数(コールバック)を渡します。算出プロパティと同じように、リアクティブな依存先を自動的に追跡して、副作用がすぐに実行されるのです(「watchEffect()」参照)。
04 リスト表示する項目を選び出して切り替える
「TodoMVC 04 リスト表示する項目を選び出して切り替える」では、つぎのフックをご紹介しています。
コンポーネントがマウントされたあと呼び出されるonMounted
フック
コンポーネントがマウントされたあとに呼び出されるコールバックを定めるのがonMounted
フックです。フックは通常つぎの場合に使われます。
- コンポーネントのレンダリングされたDOMにアクセスする必要がある副作用を実行する場合。
- サーバーレンダリングされるアプリケーションでDOM関連のコードをクライアントに限定する場合。
05 チェックをまとめてオン/オフしたり削除する
「TodoMVC 05 チェックをまとめてオン/オフしたり削除する」では、新構文やVue 3の新しい仕様に関わるご説明はありませんでした。
06 項目のテキストをダブルクリックで再編集する
「TodoMVC 06 項目のテキストをダブルクリックで再編集する」では、新構文やVue 3の新しい仕様に関わるご説明はありませんでした。
07 フォーカスをコントロールする
「TodoMVC 07 フォーカスをコントロールする」では、カスタムディレクティブについて解説しました。
カスタムディレクティブを使う
コンポーネントと同じライフサイクルに応じて、DOM要素を扱うのが「カスタムディレクティブ」です。要素に加えるカスタムディレクティブには、接頭辞v-
につづけて任意の名前を定めます。呼び出すフックオブジェクトの変数は、<script setup>
構文では、ハイフン(-)は外してv
で始まるキャメルケースをお使いください。フックオブジェクトには、ライフサイクルに応じたフック関数が加えられます(「ディレクティブフック」参照)。なお、カスタムディレクティブは、DOMを直接扱わなければならない場合にかぎって使うのがよいでしょう。
08 要素にアニメーションを加える
「TodoMVC 08 要素にアニメーションを加える」でご紹介したのは、Vue 2からVue 3で加えられた後方互換性を破る仕様変更です。
後方互換性を破るトランジションクラスの変更
<Transition>
コンポーネントを用いたトランジションクラスについて、Vue 2からVue 3で後方互換性を破るつぎのような名前の変更が行われました。-to
に対して-from
が新たに定義されたことにより、CSSの記述はわかりやすくなったでしょう。けれど、後方互換性がなくなることにご注意ください。
v-enter
トランジションクラスはv-enter-from
へ、そしてv-leaveト
ランジションクラスはv-leave-from
へと名前が変更されました(「トランジションクラスの変更」)。
(「トランジションクラスの変更」)
09 コンポーネントからロジックをコンポーザブル関数に切り分ける
「TodoMVC 09 コンポーネントからロジックをコンポーザブル関数に切り分ける」で解説したのは、 Composition APIのコンポーザブル関数です。具体的なコード例については、チュートリアル記事をお読みください。
コンポーザブル関数でコンポーネントのロジックを切り分ける
「コンポーザブル」と呼ばれる関数を用いれば、コンポーネントからロジックが切り分けられます。「『コンポーザブル(composable)』とは、Vue の Composition APIを活用して状態を持つロジックをカプセル化して再利用するための関数です」(「『コンポーザブル』とは?」)。状態の変数(オブジェクトの参照)とそれらを操作するための関数(メソッド)が備わります。コンポーザブルを呼び出したコンポーネントが戻り値として受け取るのはこうした変数や関数です。すると、コンポーネントは状態から切り離されて、ロジックが分けられます。
「Vue + <script setup>
+ TypeScript: TodoMVCチュートリアルシリーズ」から、新構文やVue 3で変わった点を拾い出してご紹介しました。体系立った取り上げ方ではなかったものの、ひとつの作例をつくり上げる中で注目された項目です。構文それぞれの使い方やコード例については、ぜひ本チュートリアルシリーズをお読みください。