Vue 3.0で導入されるcomposition apiを使って簡単なアプリケーションを作ってみる

##はじめに
vue3.0ではtypescriptとの互換性の向上やslotの扱いの変更、suspenseの追加など様々な変更点や機能追加がありますが、今回はその中でも`composition api`について触れたいと思います。細かい仕様についてお話するというより、同じアプリケーションを従来の`vue2.x`(options api)での書き方と、`vue3.x`（composition api）でどう変わるのか簡単に見ていきたいと思います。
##composition api って？
「コンポーネントロジックオン柔軟なコンポジションを可能にする機能ベースのAPIのセット」（ほぼ公式の直訳ですが）とのことです。
また、公式では以下の特徴が挙げられています。

- 保守性の向上
- 再利用性の向上

実際に簡単なアプリケーションの実装を通してこれらの変化を確認してみたいと思います！


##実際にアプリケーションを作る
無料の為替APIを使用して、inputに入力した数字をリアルタイムでドルに変換するという簡単なもの作成します。

![スクリーンショット 2020-08-27 18.33.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478762/f848e1b0-553a-bf56-14a1-4396851cf75e.png)

###Vue2.x options api での書き方
```App.vue
<template lang="pug">
    #app
        h2 currency converter
        .content__wrap
            .content__item
                span 現在
                h3 １ドル ＝
                    span  {{rates.JPY}} 円
        input(type="number" v-model="num")
        p 円 =
        p  {{result}} ドル
</template>

<script>
import axios from 'axios'
export default {
    name: 'App',
    data(){
        return {
            num:null,
            res:null,
            rates:null
        }
    },
    mounted(){
        this.getRate()
    },
    methods:{
        async getRate(){
            this.res = await axios.get(process.env.VUE_APP_API_URL)
            this.rates = this.res.data.rates
        }
    },
    computed:{
        result(){
            return this.num * this.rates.JPY
        }
    }
}
</script>

```
こちらに関してはあまり説明する必要もないかもしれませんが、`methods`で非同期処理を行い、それを`mounted`時に実行しています。また`computed`でinputで入力された値と、為替のレートをかけた値を返しています。

###Vue3.x composition api での書き方

まずは準備として、

```
npm install @vue/composition-api
```
インストール後、インポートします。

```main.js
import VueCompositionApi from "@vue/composition-api";
Vue.use(VueCompositionApi);
```

そして、先ほど同様のアプリケーションを実装していきます。

```App.vue
<template lang="pug">
    #app
        h2 currency converter
        .content__wrap
            .content__item
                span 現在
                h3 １ドル ＝
                    span  {{state.rates.JPY}} 円
        input(type="number" v-model="state.num")
        p 円 =
        p  {{state.result}} ドル
</template>

<script>
import axios from 'axios'
import { defineComponent, reactive, computed, onMounted } from '@vue/composition-api'
export default defineComponent({
    name: 'App',
    setup(){
        const state = reactive({
            num:null,
            data:null,
            rates:{},
            result:computed(() => state.num * state.rates.JPY),
        })
        async function getRate(){
            state.data = await axios.get(process.env.VUE_APP_API_URL)
            state.rates = state.data.data.rates
        }
        onMounted(() => {
            getRate()
        })
        return{
            state,
            getRate
        }
    },
})
</script>

```
パッと見結構変わってますよね。

###ざっくりどう違うのか？
`Vue2.x`での`data()`に相当するプロパティは`Vue3.x`では`setup()`で宣言します。
また、今回のアプリケーションの場合、`state,getRate`のような`templete`内で使用する関数に関しては`return`で返します。


ライフサイクルフックに関して、今回は`mounted`を使用していますが、`Vue2.x`と`Vue3.x`では書き方が大きく変わり、`Vue3.x`では`setup()`関数内で`onMounted`と宣言し設定します。そのほかのライフサイクルフックに関しても同様です。

##最後に
今回は、来たる`Vue3.x`に向けて`composition api`の書き方を試してみました。私自身まだ`options api`の書き方に慣れていますが、`composition api`はより大きなアプリケーションを構築する場合、保守性（コードの可読性）など上がってくるのかなと感じました。
やはり書き方的に大きな変化ではあるので、これまで`options api`で実装してきたサービスに一気に導入していくのはなかなか難しい部分もありそうです。

Vue3のリリースに向けさらに勉強し、ご紹介できればと思います！！