VueJS 速習チュートリアル

Vue コンポジションAPI

コンポジションAPI(Composition API)は、本チュートリアルの他のセクションで使用しているオプションAPIに代わる、Vueアプリケーションのもう一つの記述スタイルです。

コンポジションAPIでは、より自由にコードを記述できますが、その分Vueのコア・コンセプトへの深い理解が求められるため、初心者にとってはオプションAPIよりも学習コストがやや高いと考えられています。

1. コンポジションAPIの仕組み

コンポジションAPIでは、従来のオプションAPIのようなVueインスタンスの構造(data, methodsなど)に従うのではなく、Vueからインポートした関数を使用してロジック(Logic)を記述します。

以下の例は、ボタンをクリックしてストレージ内のタイプライターの在庫数を減らすアプリケーションを、コンポジションAPIで記述したものです。

1.1 実装例(コンポジションAPI)

App.vue:

<template>
  <h1>実装例</h1>
  <img src="/img_typewriter.jpeg" alt="タイプライター">
  <p>ストレージに残っているタイプライター: {{ typeWriters }}</p>
  <button @click="remove">1つ減らす</button>
  <p style="font-style: italic;">「{{ storageComment }}」</p>
</template>

<script setup>
  import { ref, computed } from 'vue'

  // typeWriters を初期値 10 のリアクティブな変数として宣言
  const typeWriters = ref(10);

  // 関数(メソッド)の定義
  function remove(){
    if(typeWriters.value > 0){
      typeWriters.value--;
    }
  }

  // Computed(算出プロパティ)の定義
  const storageComment = computed(
    function(){
      if(typeWriters.value > 5) {
        return "まだたくさんあります"
      }
      else if(typeWriters.value > 0){
        return "残りわずかです"
      }
      else {
        return "在庫がありません"
      }
    }
  )
</script>
  • 9行目: <script setup> 属性を使用することで、コンポジションAPIがさらに扱いやすくなります。この属性を使うことで、定義した変数や関数を <template> 内で直接使用できるようになります。
  • 10行目: refcomputed といった関数は、使用する前に必ずインポートする必要があります。オプションAPIでは、リアクティブな変数や算出プロパティを宣言するために何かをインポートする必要はありませんでした。
  • 12行目: ref を使用して typeWriters プロパティをリアクティブ(Reactive)として宣言しています。
    • プロパティをリアクティブにするということは、その値が変更された際に、テンプレート内の {{ typeWriters }} の表示が自動的に再レンダリングされ、最新の値が反映されることを意味します。
    • オプションAPIでは、data オプション内のプロパティはビルド時に自動的にリアクティブになりますが、コンポジションAPIでは明示的に宣言する必要があります。
  • 14行目: remove() 関数の定義です。オプションAPIであれば、これは methods プロパティの下で宣言される内容に相当します。
  • 20行目: storageComment という算出プロパティの定義です。オプションAPIであれば、これは computed プロパティの下で宣言される内容に相当します。

2. オプションAPI

オプションAPI(Options API)は、本チュートリアルの他のすべてのページで使用されているスタイルです。

このチュートリアルでオプションAPIを採用している理由は、一目でわかる明確な構造を持っており、初心者にとって学習の足がかりとして適しているためです。

例えば、オプションAPIの構造では、data プロパティ、methodscomputed プロパティがそれぞれVueインスタンス内の異なる場所に配置され、明確に分離されています。

前述のタイプライターの例を、オプションAPIで記述すると以下のようになります。

2.1 実装例(オプションAPI)

App.vue:

<template>
  <h1>実装例</h1>
  <img src="/img_typewriter.jpeg" alt="タイプライター">
  <p>ストレージに残っているタイプライター: {{ typeWriters }}</p>
  <button @click="remove">1つ減らす</button>
  <p style="font-style: italic;">「{{ storageComment }}」</p>
</template>

<script>
export default {
  // データの定義
  data() { 
    return {
      typeWriters: 10
    };
  },
  // メソッドの定義
  methods: {
    remove(){
      // this を介してデータにアクセス
      if(this.typeWriters > 0){
        this.typeWriters--;
      }
    }
  },
  // 算出プロパティの定義
  computed: {
    storageComment(){
      if(this.typeWriters > 5) {
        return "まだたくさんあります"
      }
      else if(this.typeWriters > 0){
        return "残りわずかです"
      }
      else {
        return "在庫がありません"
      }
    }
  }
}
</script>