Option APIからComposition APIへ書き換える

# Composition APIとは
Option APIではリアクティブな値をUIコンポーネントと切り離すことができなかたったが、切り離せるようにすることでコンポーネント間のロジック共有を行いやすくした技術です。コンポーネントの肥大化に苦しむプロジェクトにはメリットは大きいですが、そうでなければあえて書き直すメリットは小さそうです。また、mixinでロジックの共有化は可能でしたが、mixinを使った実装はアンチパターンとなっており、Vue3からは[非推奨となっています](https://ja.vuejs.org/api/options-composition.html#mixins
)。

# ロジックの分離
では実際にOption APIで実装していたコンポーネントのロジックをComposition APIで分離させてみます。
下記の税率計算を行うOption APIで作成したコンポーネントを例にします。
```vue:OptionApi.vue
<template>
  <div>
    <input v-model="taxExcluded" />
    <input v-model="rate" /><span>%</span>
    <span>{{ taxIncluded }}</span>
  </div>
</template>

<script>
export default {
  data() {
    return {
      taxExcluded: 0,
      rate: 10,
    }
  },
  computed: {
    taxIncluded() {
      return this.taxExcluded * this.rate * 0.01 + Number(this.taxExcluded)
    },
  },
}
</script>
```
一旦ビューとロジックは同じファイル内に置いたままComposition APIに書き換えたコードは下記です。
script内でthisを書かなくてよい代わりにリアクティブな値には`.value`でアクセスする必要があります。
```vue:CompositionApi.vue
<template>
  <!-- 省略 -->
</template>

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

export default defineComponent({
  setup() {
    const taxExcluded = ref(0)
    const rate = ref(10)

    // eslint-disable-next-line no-unused-vars
    const taxIncluded = computed(() => {
      return taxExcluded.value * rate.value * 0.01 + Number(taxExcluded.value)
    })

    return {
      taxExcluded,
      rate,
      taxIncluded,
    }
  },
})
</script>
```

ロジックとビューを分離した状態にすると下記の様になります。
```js:CalcTax.js
import { ref, computed } from 'vue'

export const calcTax = () => {
  const taxExcluded = ref(0)
  const rate = ref(10)

  const taxIncluded = computed(() => {
    return taxExcluded.value * rate.value * 0.01 + Number(taxExcluded.value)
  })

  return {
    taxExcluded,
    rate,
    taxIncluded,
  }
}
```

```vue:CompositionApi.vue
<template>
  <!-- 省略 -->
</template>

<script>
import { defineComponent } from 'vue'
import { calcTax } from '~/components/tmp/CalcTax.js'

export default defineComponent({
  setup() {
    const { taxExcluded, rate, taxIncluded } = calcTax()

    return {
      taxExcluded,
      rate,
      taxIncluded,
    }
  },
})
</script>
```

# Composition APIの書き方
以下、Option APIとCompositionAPIでのdataやmethodsの書き方の違いです。
## data
```js
// Option API
data() {
  return {
    hoge: 0
  }
}

// Composition API
const hoge = ref(0)
```

## methods
```js
// Option API
methods: {
  hogeMethod() {
    this.hoge1 + this.hoge2
  }
}

// Composition API
const hoge = () => {
  hoge1.value + fuga2.value
}
```

## computed
```js
// Option API
computed: {
  hoge() {
    this.hoge1 + this.hoge2
  }
}

// Composition API
const hoge = computed(() => {
  hoge1.value + hoge2.value
})
```

## props
```js
// Option API
props: {
  hoge: {
    type: String,
    default: '',
  }
}

// Composition API
const props = defineProps({
  hoge: {
    type: String,
    default: '',
  }
})
```

# ライフサイクル
Composition APIではライフサイクルが変更されています。
全体的に名称が変わっているほか、`beforeCreate`と`created`のライフサイクルはsetupで実行されるようになりました。
| Option API | Composition API |
| --- | --- |
| beforeCreate | setupに記述 |
| created | setupに記述 |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeUnmount | onBeforeUnmount |
| unmounted | onUnmounted |
| errorCaptured | onErrorCaptured |
| renderTracked | onRenderTracked |
| renderTriggered | onRenderTriggered |
| activated | onActivated |
| deactivated | onDeactivated |


# おわりに
Composition APIを使うことでロジックを分離できる上に、機能ごとにロジックをまとめやすくもなるためよりVueが使いやすくなりますね。

# 参考
https://v3.ja.vuejs.org/api/composition-api.html

https://tomosta.jp/2022/06/vue3-begin/

https://ics.media/entry/210929/