Vue Composition APIについて調べてみた件

夏休み記事1件目です
（ホントはchefの記事を書いていたのですが、どうにもエラーが解決できなかったので先にこちらです）

Vue3について調べたり試したりしたことを忘れないように書き留めました。
間違ってるところがありましたら、優しくご指摘していただけると幸いです。

# composition APIって？
> 関数ベースで提供されるAPI郡
[まもなくやってくるvue.js3 23ページ](https://speakerdeck.com/kazupon/mamonakuyatutekuru-vue-dot-js-3?slide=23)より

つまり、用意された関数を使っていろいろできる

## なんでこれが必要なの？
いままでのVueでは以下のことが問題でした。

- コンポーネントが大きくなるとコードの可読性が落ちる
- テストしにくい
- コード再利用のパターン化がしにくい
- TypeScriptによる型のサポートが受けにくい

今まで、変数の宣言は`data()`でやって、処理する関数は、`methods()`で書いていて、コンポーネントを上下に行ったり来たりしていたものが、これで改善されるかんじですかね？

## 提供される主なAPIの種類

- リアクティブ状態の操作
- コンポーネントの新エントリーポイント
- ライフサイクルフック
- Dependency injection(依存性の注入)

### リアクティブとは？
> ある変数を書き換えた時に、事前に定めた関係性を元に、他の変数が適切に更新されたり、事前に定めた動作が発動することを「リアクティブである」と言います
[きたるべきvue-nextのコアを理解する - そもそも「リアクティブ」とは?](https://qiita.com/neutron63zf/items/506c7493a53cea44860e#vue-next%E3%81%AE%E3%83%AA%E3%82%A2%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)
### リアクティブ状態の操作

| API名     | 内容 |
| ---       | --- |
| reactive  | オブジェクトを取得し、元のオブジェクトの反応型プロキシを返す。2.xの`Vue.observable()`と同じ。 |
| ref       | 内側の値を取得して、反応性があり、変更可能な ref オブジェクトを返す。|
| readonly  | オブジェクトまたはrefを取得し、読み込み専用のプロキシを元のオブジェクトに返す。|
| computed  | getter関数を受け取り、getterから返された値に対して不変の反応型 ref オブジェクトを返す。|
| watch     | watch は特定のデータソースを監視し、別のコールバック関数を適用する。2.x の this.$watch と同じ。|
| watchEffect| 依存関係を反応的に追跡しながら即座に関数を実行し、依存関係が変更された場合はいつでも再実行する。|

その他にもAPIがあるので気になる方は[Vue composition API](https://vue-composition-api-rfc.netlify.app/api.html#setup)を見てみてください

### ライフサイクルフック
コンポーネントの新エントリーポイントはあとで`setup`でちょこっと触れるので省略します。
今までのものとcomposition APIのライフサイクルフックの対応は以下のようになっています

| Vue 2.x | Compostion API |
|:--|:--|
| beforeCreate | setup |
| created | setup |
| beforeMount | onBeforeMount |
| beforeUpdate | onBeforeUpdate |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |
| errorCaptured | onErrorCaptured |

[情報ソース](https://speakerdeck.com/kazupon/mamonakuyatutekuru-vue-dot-js-3?slide=40)
## 実際に触ってみる
今回は`reactive`と`ref`について見ていきます。

vueのプロジェクトを作成してvue3の各機能が使えるように`vue-next`を追加します

```bash
vue create try-composition
cd try-composition
vue add vue-next
```

早速composition APIを使ってみたいと思います

```vuejs:App.vue
<template>
  <div>{{ count }} {{ object.foo }}</div>
</template>

<script>
  import { ref, reactive } from 'vue'

  export default {
    setup() {
      const count = ref(0)
      const object = reactive({ foo: 'bar' })

      // expose to template
      return {
        count,
        object
      }
    }
  }
</script>
```

`setup`関数はコンポーネント内でコンポジションAPIを使うためのエントリーポイントとして機能するようです。
`return`したものがテンプレートのレンダリングコンテキストになるそうです。

これで`npm run serve`すると以下のように表示されます。
![FireShot Capture 013 - vue3-test - localhost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/adfc9236-ee25-2e7d-1c7d-d2137cc58f68.png)

`ref`を使った場合`value`という内部値を指すプロパティーがあります。
これをつかって値の操作ができます。

```vuejs:App.vue
<template>
  <div></div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup () {
    const count = ref(0)
    console.log(count.value)

    count.value++
    console.log(count.value)

    // expose to template
    return {
    }
  }
}
</script>
```

変更してコンソールを見てみるとこのようになっています。
しっかり値が1プラスされてます。

![Screenshot from 2020-08-09 18-08-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/7dd7cc96-94bf-62e5-b541-c0a495b67817.png)

では、refで宣言したものを再度reactiveで使ったらどうなるでしょうか？
以下のコードで試してみます。

```vuejs:App.vue
const count = ref(0)
const state = reactive({
  count
})

console.log(state.count)

state.count = 1
console.log(count.value) 
```

変更してコンソールを見てみると、このように`count`に代入されています。
参照渡しされているっぽいですね。


![Screenshot from 2020-08-09 18-08-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/7dd7cc96-94bf-62e5-b541-c0a495b67817.png)

## `ref`と`reactive`の違いは？
`ref`と`reactive`はどちらもリアクティブなデータを実現するという点では一緒です。
[公式のページ](https://vue-composition-api-rfc.netlify.app/#ref-vs-reactive)を見てみると、
>The difference between using ref and reactive can be somewhat compared to how you would write standard JavaScript logic:
(翻訳)ref と reactive の違いは、標準的な JavaScript ロジックの書き方と比較すると、多少の違いがあります。


具体的には以下のコードが紹介されています。

```js
// style 1: 別々の変数
let x = 0
let y = 0

function updatePosition(e) {
  x = e.pageX
  y = e.pageY
}

// --- compared to ---

// style 2: １つのオブジェクト
const pos = {
  x: 0,
  y: 0
}

function updatePosition(e) {
  pos.x = e.pageX
  pos.y = e.pageY
}
```

| 対象 | 該当箇所 | 内容 |
| --- | --- | --- |
|  ref  |  style 1に該当する  |  個別に変数宣言する  |
|  reactive  |  style 2に該当する  | オブジェクトでまとめて宣言する  |

読んで試した結果、オブジェクトなのか、別々の変数なのかというかんじなのでしょうか？

公式の説明の翻訳は以下のようです。
> ref を使用する場合は、スタイル (1) を refs を使用してより冗長な同等のものに大部分を変換しています (プリミティブ値をリアクティブにするため)。
reactive を使うことは、スタイル (2) とほぼ同じです。リアクティブを使ってオブジェクトを作成するだけで、それだけです。
しかし、リアクティブのみにする場合の問題は、合成関数の消費者がリアクティブを保持するためには、返されたオブジェクトへの参照を常に保持していなければならないということです。オブジェクトを破壊したり、拡散したりすることはできません。

まだまだ理解ができていないので、これからもっと調べて試していきたいと思います。

# おわりに
自分自身、調べた結果を忘れないために書いたので、間違いなどがあると思います。
もし「ここ違うんじゃ？」などあったら、教えていただけると幸いです。

#　参考にした記事や引用元

- [Vue composition API](https://vue-composition-api-rfc.netlify.app/api.html#setup)
- [Ref vs. Reactive](https://vue-composition-api-rfc.netlify.app/#ref-vs-reactive)
- [Vue.jsのcomposition-apiにおける"ref"と"reactive"って何が違うの？](https://qiita.com/mgr/items/a5e35636d371969e0a4d)
- [【Vue3に備える】実務で使うComposition APIについて考える](https://medium.com/finatext/composition-api-for-vue3-63631dbadcef)