Composition APIを利用したロジックの共通化
Composition APIでは、JavaScriptの標準的な記法でデータ/メソッド/算出プロパティなどを記述できるため、ロジックの共通化が容易です。例えば、iOSとAndroidで共通の処理内容を、リスト8の通り切り出せます。リスト8のPhonesLogicメソッドでは、受け取った引数でデータの初期値を設定し、メソッドや算出プロパティと合わせて返却します。
import { reactive, computed, toRefs } from 'vue' export default function PhonesLogic(initialList) { // reactiveでデータを記述 const state = reactive({ terminals: initialList, newTerminal: '' }) // メソッド function addNew() { state.terminals.push(state.newTerminal) state.newTerminal = '' } // 算出プロパティ const count = computed(function () { return state.terminals.length }) // ここまで定義してきた内容を返却 return { ...toRefs(state), addNew, count } }
リスト8の共通ロジックを利用するコンポーネントの実装はリスト9です。(1)でiOS/Androidの各処理を行うロジックを生成し、(2)で総端末数の算出プロパティを定義後、(3)で各ロジックと算出プロパティをまとめてreturnします。
setup() { // PhoneLogicでiOS/Androidの各処理ロジックを生成 ...(1) const iOSLogic = PhonesLogic(['iPhone 11']) const androidLogic = PhonesLogic(['Galaxy S20 5G']) // 総端末数を計算する算出プロパティ ...(2) const countTotal = computed(function() { return iOSLogic.count.value + androidLogic.count.value }) // ここまで定義してきた内容を返却 ...(3) return { iOSLogic, androidLogic, countTotal } }
応用的なトピック:プロパティとライフサイクルフック
以下では応用的なトピックとして、プロパティとライフサイクルフックをComposition APIで記述する方法を、図2のサンプルで説明します。このサンプルでは、プロパティで機種名/メーカー/重量を設定できるコンポーネントを表示します。コンポーネントがWebページに追加(マウント)された時のライフサイクルフックでログを出力します。
Options APIで記述したコンポーネントはリスト10です。(1)のpropsで、String型のname(機種名)とvendor(メーカー)、Number型のweight(重量)プロパティを設定します。(2)ではvendorとnameを結合して取得する算出プロパティfullNameを記述していますが、プロパティ値を取得するには(3)の通り「this.<プロパティ名>」とします。(4)はコンポーネントの追加(マウント)時に実行されるmountedライフサイクルフックです。
<template> <div class="one-phone"> <h3>{{ fullName }}</h3> <div>機種名:{{ name }}</div> <div>メーカー:{{ vendor }}</div> <div>重量:{{ weight }}g</div> </div> </template> <script> export default { // プロパティの設定 ...(1) props: { name: String, vendor: String, weight: Number }, // 算出プロパティ ...(2) computed: { fullName() { // thisでプロパティを参照 ...(3) return this.vendor + ':' + this.name } }, // mountedライフサイクルフック ...(4) mounted() { console.log('コンポーネントがマウントされました') } } </script>
同じコンポーネントをComposition APIで記述した<script>部はリスト11となります。<template>部はリスト10と同一です。
export default { // プロパティの設定 ...(1) props: { name: String, vendor: String, weight: Number }, // setupメソッドの引数propsにプロパティが含まれる ...(2) setup(props) { // 算出プロパティ ...(3) const fullName = computed(function() { // propsでプロパティを参照 ...(4) return props.vendor + ':' + props.name }) // onMountedライフサイクルフック ...(5) onMounted(function() { console.log('コンポーネントがマウントされました') }) return { fullName } } }
プロパティ設定(1)の記述はリスト10と同一です。setupメソッド(2)の引数propsにプロパティ値が含まれるため、fullName算出プロパティ(3)でプロパティ値を参照するには(4)の通り「props.<プロパティ名>」とします。
ライフサイクルフックは(5)の通り、処理内容のfunctionをonMountedメソッドの引数に与えて記述します。なおVue 3では、利用できるライフサイクルフックがVue 2から細かく変更されています。詳細はComposition APIのドキュメントを参照してください。
まとめ
本記事では、Vue.jsの次期バージョン「Vue 3」で導入される新機能のうち、新しいコンポーネント記述形式であるComposition APIについて説明しました。コンポーネント機能の実装が分散したり、再利用が難しかったりするといった、従来のコンポーネント記述形式(Options API)が抱える問題点を、Composition APIを利用して解決できます。Composition APIの利点を生かしてロジックを共通化する例を、記事内で紹介しました。
次回は、Vue 3に導入されるComposition API以外の新機能を紹介していきます。