業務でOptions APIで書かれたVue.jsのファイルをComposition APIに書き換える作業がありました。どのように対応すれば良いか迷ったため、備忘録としてまとめます。
最後まで読めば、Options APIとComposition APIの記述の違いや書き換え方法が理解できるかなと思います。
なお今回は以下のようなFizzBuzz形式のカウントアプリを題材とします。通常はカウントされた数値がそのまま表示されますが、数値が3で割り切れる場合はFizzを、5で割り切れる場合はBuzzを、3でも5でも割り切れる場合はFizzBuzzという文字を表示します。
Options APIのコード
早速ですが、上記のカウントアプリをOptions APIで実装すると次のようになります。
<template>
<div class="home">
<div>
<button @click="decreaseCounter" class="btn">-</button>
<span class="counter">{{ counter }}</span>
<button @click="increaseCounter" class="btn">+</button>
</div>
<div>{{ fizzBuzzText }}</div>
</div>
</template>
<script>
export default {
data(): { counter: number } {
return {
counter: 1,
};
},
computed: {
fizzBuzzText(): string {
if (this.counter % 3 === 0 && this.counter % 5 === 0) return 'FizzBuzz';
if (this.counter % 3 === 0) return 'Fizz';
if (this.counter % 5 === 0) return 'Buzz';
return this.counter.toString();
}
},
methods: {
increaseCounter(): void {
this.counter++;
},
decreaseCounter(): void {
this.counter--;
},
},
};
</script>
<style>
.home {
text-align: center;
padding: 20px;
}
.btn,
.counter {
font-size: 40px;
margin: 10px;
}
</style>
data
、computed
、method
など複数のオプションを用いてコンポーネントのロジックを表現します。またこれらのオプションによって定義したプロパティにはthis
を使うことでアクセス可能です。
ただしOptions APIではオプション毎のまとまりで記述しなくてはいけません。今回のようにシンプルなアプリであれば全く問題ないですが、複雑になってくるとdata
オプションとmethod
オプションをスクロールで行ったり来たりしないと、関連性が把握できなくなってしまいます。またthis
を使ってプロパティにアクセスするため、ロジックを別ファイルに分離することが困難になってしまいます。
そこでCompositions APIの登場です。
Options APIからComposition APIに書き換えるポイント
Composition APIのコード例を見る前に一点だけ補足です。Options API から Composition API に書き換えるときは、<template>
部分には手を加えず、<script>
の中だけを修正しましょう。
Composition APIのコード例(setup関数を使用)
Composition APIを採用すると、同じアプリのコードが次のように書けます。
<template>
<div class="home">
<div>
<button @click="decreaseCounter" class="btn">-</button>
<span class="counter">{{ counter }}</span>
<button @click="increaseCounter" class="btn">+</button>
</div>
<div>{{ fizzBuzzText }}</div>
</div>
</template>
<script lang="ts">
import { computed, ref } from 'vue';
export default {
setup() {
const counter = ref(1);
const fizzBuzzText = computed(() => {
if (counter.value % 3 === 0 && counter.value % 5 === 0) return 'FizzBuzz';
if (counter.value % 3 === 0) return 'Fizz';
if (counter.value % 5 === 0) return 'Buzz';
return counter.value.toString();
});
const increaseCounter = (): void => {
counter.value++;
};
const decreaseCounter = (): void => {
counter.value--;
};
return {
counter,
fizzBuzzText,
increaseCounter,
decreaseCounter,
};
},
};
</script>
<style>
.home {
text-align: center;
padding: 20px;
}
.btn,
.counter {
font-size: 40px;
margin: 10px;
}
</style>
オプションによる区切りはなくなり、setup()
関数の中で任意の順番で書くことができます。これにより関連する変数や関数を一箇所にまとめて記述できるようになりました。ただし定義した関数・変数はsetup()
関数の末尾でreturn
する必要があります。
Composition APIのコード例(<script setup>使用, Vue3.2以降)
さらにVue3.2以降では<script setup>
という書き方もできます。この方法だとsetup()
関数を書く必要もなければ末尾でreturn
する必要もないため、よりシンプルに記述できます。現時点ではこの書き方が推奨されています。
<template>
<div class="home">
<div>
<button @click="decreaseCounter" class="btn">-</button>
<span class="counter">{{ counter }}</span>
<button @click="increaseCounter" class="btn">+</button>
</div>
<div>{{ fizzBuzzText }}</div>
</div>
</template>
<script setup>
import { computed, ref } from 'vue';
const counter = ref(1);
const fizzBuzzText = computed(() => {
if (counter.value % 3 === 0 && counter.value % 5 === 0) return 'FizzBuzz';
if (counter.value % 3 === 0) return 'Fizz';
if (counter.value % 5 === 0) return 'Buzz';
return counter.value.toString();
});
const increaseCounter = (): void => {
counter.value++;
};
const decreaseCounter = (): void => {
counter.value--;
};
</script>
<style>
.home {
text-align: center;
padding: 20px;
}
.btn,
.counter {
font-size: 40px;
margin: 10px;
}
</style>
まとめ
Options APIからComposition APIの書き方の違いを理解できました。
コメント