225
136

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

6歳娘「パパ、Vue3のComposition APIってどう使うの?」

Last updated at Posted at 2022-07-03

今回使った技術

  • Vue3
  • Nuxt3(ベータ版)
  • TypeScript

ある日の我が家

娘「ねぇ、パパ!」
娘「Vue3の、Composition APIの使い方を教えて!」

ワイ「おお、ええで〜」
ワイ「ほな、試しにこんな感じのページを作っていくで!」

スクリーンショット 2022-07-03 11.01.27.png

娘「わー、数をカウントできるページなんだ!」
娘「便利そう〜!」
娘「しかも、2倍の数も確認できるんだね!」

ワイ「げへへ、照れるでぇ」
ワイ「ほな、さっそく作っていくで〜」

カウンターを作っていく

ワイ「まずは、カウンターの数値が今いくつなのか」
ワイ「その状態管理をせなあかんから」

/pages/index.vue
<script lang="ts">
export default defineComponent({
+ data() {
+   return {
+     count: 0
+   };
+ },
})
</script>

ワイ「↑こうや!」

娘「なるほど〜」
娘「状態管理したい値は、data()っていう関数の戻り値として書くんだね!」

ワイ「せやで〜」
ワイ「そして、2倍のカウントを表示するためには・・・」

/pages/index.vue
<script lang="ts">
export default defineComponent({
  data() {
    return {
      count: 0
    };
  },
+ computed: {
+   double() {
+     return this.count * 2
+   }
+ },
})
</script>

ワイ「↑こうや!」

娘「countと連動した値を表示したい場合には」
娘「computedの中に関数を書けばいいんだね!」

ワイ「そうや!」

娘「パパ、HTML部分は書かなくていいの?」

ワイ「おお、せやったな!」

/pages/index.vue
<template>
  <h1>カウントするページ</h1>
  <p>カウント:{{ count }}</p>
  <p>カウント(2倍):{{ double }}</p>
  <button @click="decrement">減らす</button>
  <button @click="increment">増やす</button>
</template>

ワイ「↑こんな感じや!」
ワイ「ここで1回、画面を見てみよか」

スクリーンショット 2022-07-03 11.07.04.png

ワイ「おお、できとるできとる」

娘「でも、なんかエラーが出てるよ?」

スクリーンショット 2022-07-03 11.11.09.png

ワイ「おお、まだdecrementincrementの関数を書いてないからやな」
ワイ「ほな、その2つの関数を書いていくで!」

/pages/index.vue
<script lang="ts">
export default defineComponent({
  data() {
    return {
      count: 0
    };
  },
  computed: {
    double() {
      return this.count * 2
    }
  },
+ methods: {
+   increment() {
+     this.count++
+   },
+   decrement() {
+     this.count--
+   },
+ },
})
</script>

ワイ「↑こうやな!」

娘「へぇ、関数はmethodsの中に書くんだね!」

ワイ「せやで〜」
ワイ「これで完成や!」
ワイ「動かしてみるで〜」
ワイ「ボタンをポチ、ポチと」

スクリーンショット 2022-07-03 11.01.27.png

娘「本当だ、ちゃんと数をカウントできてる〜!」
娘「これで、数を数えられないパパでも安心だね!」

ワイ「いやそこまでアホちゃうわ」

しかし娘ちゃん、思ってたのと違う

娘「・・・あれ?」
娘「でもこれ、Vue3の書き方っていうか」
娘「Vue2の書き方にそっくりじゃない?」

ワイ「せやで」
ワイ「Vue2の時からあるOptions APIの書き方やで」

娘「私が教えて欲しかったのは、Composition APIの方だよ」

ワイ「・・・せやったな」
ワイ「でも大丈夫やで」
ワイ「Options APIからComposition APIに」
ワイ「シームレスに書き換えていくこともできるからな」

娘「そうなんだ」

Composition APIに書き換えていく

ワイ「まず、状態管理したい値が書いてあるdata()の部分は」

/pages/index.vue
<script setup lang="ts">
+ const count = ref(0)
</script>

<script lang="ts">
export default defineComponent({
- data() {
-   return {
-     count: 0
-   };
- },
  computed: {
    double() {
      return this.count * 2
    }
  },
  methods: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    },
  },
})
</script>

ワイ「↑こうしてやるんや」

娘「へぇ〜」

/pages/index.vue
<script setup lang="ts">
</script>

娘「↑この中に」

/pages/index.vue
<script setup lang="ts">
+ const count = ref(0)
</script>

娘「↑こう書いてあげるんだ1

ワイ「せやで」
ワイ「ほな、動作確認してみるで」

娘「え?」
娘「こんな中途半端な状態で動くの?」

ワイ「ああ、せやで」

スクリーンショット 2022-07-03 11.01.27.png

ワイ「↑ほらな」

娘「ほんとだ、ちゃんと動いてる」
娘「へ〜」
娘「Options APIとComposition APIって、併用できるんだ」
娘「それなら、少しずつ移行できて良さそうだね!」

ワイ「せやで」
ワイ「ただ・・・」

/pages/index.vue
<script setup lang="ts">
  const count = ref(0)
</script>

ワイ「↑この<script setup lang="ts">の中に書いたコードが」
ワイ「data()とかcomputedとかmethodsよりも先に実行されるから」
ワイ「移していく順番は考えないとアカンみたいや」

娘「なるほどね」

computedを移行する

ワイ「次は、computedの中身を、setupの方に移していくで」

/pages/index.vue
<script setup lang="ts">
  const count = ref(0)
+ const double = computed(() => count.value * 2)
</script>

<script lang="ts">
export default defineComponent({
- computed: {
-   double() {
-     return this.count * 2
-   }
- },
  methods: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    },
  },
})
</script>

ワイ「↑こうやな!」

娘「へぇ〜」

/pages/index.vue
<script setup lang="ts">
  const count = ref(0)
+ const double = computed(() => count.value * 2)
</script>

娘「computedっていう関数に、関数を渡してあげる感じなんだね」

ワイ「せやで〜」

methodsを移行する

ワイ「ほな、methodsの中身も」
ワイ「setupの方に移していくで〜」

/pages/index.vue
<script setup lang="ts">
  const count = ref(0)
  const double = computed(() => count.value * 2)
+ const increment = () => count.value++
+ const decrement = () => count.value--
</script>

<script lang="ts">
export default defineComponent({
- methods: {
-   increment() {
-     this.count++
-   },
-   decrement() {
-     this.count--
-   },
- },
})
</script>

ワイ「↑こうや!」

娘「へぇ〜」
娘「methodsの中にあった関数は、単純に関数を書けばいいんだね!」

ワイ「せや」
ワイ「これで、下の方の<script>タグは要らんくなるから」

/pages/index.vue
<script setup lang="ts">
  const count = ref(0)
  const double = computed(() => count.value * 2)
  const increment = () => count.value++
  const decrement = () => count.value--
</script>

- <script lang="ts">
- export default defineComponent({
- })
- </script>

ワイ「↑こうやな」
ワイ「ほな、動作確認してみるで」

スクリーンショット 2022-07-03 11.01.27.png

ワイ「よっしゃ、ちゃんと動いとるわ」

娘「わーい!」

なぜComposition APIなのか

ワイ「でも、なんでComposition APIなんてものが登場したんやろなぁ」
ワイ「Options APIの方が・・・」

  • 状態管理したい値はdata()に書く
  • 状態と連動して表示したい値はcomputedに書く
  • 関数はmethodsに書く

ワイ「↑こんな感じで、メッチャ分かりやすいと思うけどなぁ」

娘「それも分かるけど、私はComposition APIの方が好きだよ」
娘「状態管理する値はここ、とか」
娘「関数はここ、とか」
娘「そういう分け方じゃなく」
娘「カウンター関連の処理はここ、っていう感じで」
娘「コードをまとめることができるじゃん?」

ワイ「ああ〜、確かに」
ワイ「状態かどうか、関数かどうか、じゃなくて」
ワイ「カウンター関連の処理かどうか・・・にフォーカスを当てて」
ワイ「コードをまとめられるなぁ」

娘「うん」
娘「関心事の単位でコードをまとめれるから、私は好き」

ワイ「Options APIで書いた場合だと」
ワイ「カウンター関連の処理を修正したい場合なんかに」
ワイ「data()の中を直して、computedの中を直して、methodsの中も・・・って感じで」
ワイ「修正箇所がバラバラで、ちょっと探しにくかったもんな」

娘「そうそう」
娘「それに、このカウンター関連のロジックを」
娘「別のページでも使いたくなったときに、すごくやりやすいらしいよ」

ワイ「へぇ〜」

娘「ちょっとやって見せるね」

カウンター関連の処理を、別ファイルに切り出す

娘「さっき<script setup lang="ts">の中に書いた内容を」

/composables/count.ts
export const useCounter = () => {
  const count = ref(0)
  const double = computed(() => count.value * 2)
  const increment = () => count.value++
  const decrement = () => count.value--

  return {
    count,
    double,
    increment,
    decrement,
  }
}

娘「↑こう、別ファイルに切り出すの」

ワイ「ほうほう」

娘「そして、ページの方から・・・」

/pages/index.vue
<script setup lang="ts">
import { useCounter } from '~~/composables/count'

const { count, double, increment, decrement } =  useCounter()
</script>

娘「↑こう呼び出して使ってあげるの」

ワイ「ほうほう」

娘「こうしてあげることで、同じロジックを」
娘「色んなページで使い回すこともできるよ!」

ワイ「おぉ〜、ホンマやね」
ワイ「Options APIの場合だと、その辺ちょっとやりづらかったもんなぁ」
ワイ「Mixinとか、あるにはあったけど」

娘「そうだね」
娘「つまり・・・」

  • ページやコンポーネントの中から、状態関連のロジックを抽出できる
  • いろんな場所で再利用できる

娘「↑こういうことが、Composition APIのおかげでやりやすくなったよね!」

ワイ「確かに・・・!」

まとめ

  • Options APIの場合
    • 「状態かどうか」「関数かどうか」でコードの場所が決まる
  • Composition APIの場合
    • 関心事の単位でコードをまとめられる
    • 状態関連のロジックを抽出して、再利用できる
  • Vue3でもOptions APIは使える
  • Options APIとComposition APIは、1ファイルの中でも併用可能
  • Options APIからComposition APIへ、動作確認しながら段階的に移行することも可能

ワイ「↑こういうことやな!」

娘「そうだね!」

〜おしまい〜

参考文献

こちらの記事もよろしくやで!

  1. ref()じゃなくてreactive()ってやつもあります。

225
136
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
225
136

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?