Composition APIだけではない、Vue 3の新機能(2)
コンポーネント内容を任意の場所に移動するTeleport
Teleportは、コンポーネント内容の一部を、Webページ内の任意の場所に移動(テレポート)する機能です。モーダルダイアログやポップアップなど、コンポーネント外部に記述する必要があるHTML要素に、コンポーネント内容を反映する場合などに利用できます。図2のサンプルでは、コンポーネント内容の一部を、コンポーネント外(index.htmlに記述したHTML要素)にテレポートしています。
コンポーネントの<template>部をリスト3に示します。(1)の通り、移動させる内容を<teleport>タグで囲み、to属性にテレポート先のCSSセレクター(ここでは「teleport-target」ID)を指定します。
<template> <div id="teleport-component"> <h3>Teleport元(コンポーネント)</h3> <div>↓↓↓↓Teleport元↓↓↓↓</div> <teleport to="#teleport-target"> <!--(1)--> このテキストがTeleportされます </teleport> <div>↑↑↑↑Teleport元↑↑↑↑</div> </div> </template>
移動先ではリスト4(1)の通り、<teleport>タグのto属性に指定したCSSセレクターに対応するようにIDを設定しておきます。
<h3>Teleport先(index.html)</h3> <div>↓↓↓↓Teleport先↓↓↓↓</div> <div id="teleport-target"></div> <!--(1)--> <div>↑↑↑↑Teleport先↑↑↑↑</div>
実行すると、リスト3(1)のteleportタグ内に記述された文言「このテキストがTeleportされます」が、リスト4(1)の部分に移動(テレポート)して表示されます。
<template>直下に複数のタグが記述できるFragment
Vue 3ではFragment(複数のルートノードを持つコンポーネント)が利用できます。従来<template>の直下に記述できるタグは1つだけだったので、全体を単一の<div>タグで囲むのが一般的でしたが、例えばコンポーネントの上位に<ul>タグがあり、コンポーネント内に複数の<li>タグがあるといった構造を実現できませんでした。Vue 3ではリスト5の通り、複数タグを記述して対応できます。
<template> <!-- このコンポーネントはulタグの中に表示される --> <li>iPhone 11</li> <li>Galaxy S20 5G</li> <li>AQUOS R5G</li> </template>
コンポーネント準備中の表示を実現するSuspense
Suspenseは、コンポーネント準備中の表示(ロード中など)を指定できる機能です。
図3のサンプルの<template>部は、リスト6の通りです。<Suspense>タグ内に、コンポーネント(1)と、準備完了までの表示(2)に対応する2個の<template>を記述します。(1)には、準備完了までの時間が異なる(3秒と4秒)2個のコンポーネントが含まれますが、両方の準備が完了後(つまり4秒後)に表示が切り替わります。
<template> <Suspense> <template #default> <!--(1)--> <async-component1/> <!-- 3秒後に準備完了するコンポーネント --> <async-component2/> <!-- 4秒後に準備完了するコンポーネント --> </template> <template #fallback> <!--(2)--> 全コンポーネントの準備完了を待っています... </template> </Suspense> </template>
オブジェクトや配列のバインディング改善
Vue 2では、配列要素の更新やオブジェクトのプロパティ追加/削除を画面に反映させるには、Vue.setやVue.deleteメソッドで間接的に操作する必要がありました。
// 配列要素の更新 // this.dataArray[0] = this.inputValue <- これでは画面に反映されない Vue.set(this.dataArray, 0, this.inputValue) // オブジェクトのプロパティ削除 // delete this.dataObj.name <- これでは画面に反映されない Vue.delete(this.dataObj, 'name')
Vue 3ではオブジェクトや配列のバインディングが改善され、配列要素の更新やオブジェクトのプロパティ追加/削除が、そのまま画面に反映されるようになりました。
// 配列要素の更新 state.dataArray[0] = state.inputValue; // オブジェクトのプロパティ削除 delete state.dataObj.name
新しいアプリ開始処理createApp
従来アプリ開始処理で利用していたVueオブジェクトに代わって、Vue 3ではcreateAppメソッドを利用するようになりました。
// 従来の開始処理 new Vue({ render: h => h(App), }).$mount('#app') // Vue 3の開始処理 createApp(App).mount('#app')
フィルターの廃止
フィルターは、変数をWebページに反映するときに内容を加工する機能ですが、メソッドで代用できることから、Vue 3では廃止されました。入力文字列を大文字に変換して表示する図4のサンプルで、フィルターとその代用方法を説明します。
Vue 2でフィルターを利用した実装をリスト10に示します。
<template> <div> <input v-model="inputValue"> <div>大文字:{{ inputValue | uppercase }}</div> <!--(1)--> </div> </template> <script> export default { data() { return { inputValue: '' } }, filters: { // 大文字に変換するフィルター ...(2) uppercase(value) { if (!value) return '' return value.toString().toUpperCase() } } } </script>
フィルターの処理は、(2)のfiltersで実装します。ここでは大文字に変換するフィルターuppercaseを実装しています。このフィルターを利用して(1)で「{{ inputValue | uppercase }}」と記述することで、inputValueにuppercaseフィルターを適用して大文字にしています。
同じ処理をVue 3で実装したものをリスト11に示します。
<template> <div> <input v-model="inputValue"> <div>大文字:{{ uppercase(inputValue) }}</div> <!--(1)--> </div> </template> <script> import { ref } from 'vue' export default { setup() { const inputValue = ref('') // 大文字に変換するメソッド ...(2) function uppercase(value) { if (!value) return '' return value.toString().toUpperCase() } return { inputValue, uppercase } } } </script>
(2)で実装した大文字変換メソッドuppercaseを、(1)で「{{ uppercase(inputValue) }}」と利用することで、inputValueを大文字にしています。
TypeScriptサポートの改善
Vue 3はそれ自身がTypeScriptで開発されており、TypeScriptサポートが改善されています。TypeScript環境でComposition APIを利用する場合、リスト12の通りdefineComponentメソッドを利用すると、型推論が有効になります。
export default defineComponent({ setup() { (略) } })
TypeScript環境では、reactiveやrefメソッドで記述するデータ変数に型を指定できます。reactiveの型指定はリスト13の通りです。reactiveメソッドの<>記述で、iOSとandroidにはstring配列、newIOSとnewAndroidにはstringの型を指定しています。
const state = reactive<{ iOS: Array<string>; newIOS: string; android: Array<string>; newAndroid: string; }>({ iOS: ['iPhone 11'], newIOS: '', android: ['Galaxy S20 5G'], newAndroid: '' })
同じ型指定をrefで行う場合はリスト14の通り記述します。refメソッドの<>記述で、それぞれの型を指定しています。
const iOS = ref<Array<string>>(['iPhone 11']) const newIOS = ref<string>('') const android = ref<Array<string>>(['Galaxy S20 5G']) const newAndroid = ref<string>('')
なお、TypeScriptに対応したVue 3のプロジェクトをVue CLIで生成する方法は、p009-ts-reactive/p010-ts-refサンプルコードのREADME.mdを参照してください。
まとめ
本記事では、Vue.jsの次期バージョン「Vue 3」に導入される、Composition API以外の新機能について説明しました。大小さまざまな新機能は、Vue.jsの使い勝手をより一層高めるものになっています。
参考資料