今までVue 2に慣れ親しんできたのでVue 3をキャッチアップする

## 対象読者
Vue 2をこれまでやったことがあって今後Vue 3もキャッチアップしたい方
そのため本記事はVue 2をやってきた前提で説明します。

## 本記事を書こうと思ったきっかけ
- 今後仕事などで触れる機会が出てきそう
- Nuxtももうすぐバージョン3が出る
  （本当はこれの記事にしようと思ったが、ベータ版リリースが10/12(火)夜で丁度間に合わず）
- Vuexも今後出るバージョン5で長年問題だったTypeScriptとの互換性が解消されるらしい
- Composition APIの記事を読んでたらComposition APIが面白そうに感じた

https://zenn.dev/azukiazusa/articles/38e9f804474668

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

とこんな感じでとりあえず少しずつ齧っていこうと思ったのがきっかけです。

## Vue 3で新しく登場した主な機能と特徴
追加した主な機能はこちらとなります。
今回の記事では`Composition API`と`Fragments`を紹介します。

- Composition API
- Teleport
- Fragments
- Emits Component Option
- Suspense（現時点では実験段階、本番環境での使用はまだダメ）

また、Internet Explorer11は**非対応**となりました。

## どんな形でキャッチアップした？
公式のドキュメントを主に読みました（日本語化済み）。
ドキュメントにも記載がある通り、Vue 2を一通りやってきた人は「Vue 2からの移行」ページに書かれているページさえ読めば大丈夫です。

https://v3.ja.vuejs.org/guide/migration/introduction.html

また下のサイトはVue 3の概要についてわかりやすく書いてくれていました。Vue2をずっとやってきた人はまずここを読むと頭に入ってきやすいと思います。

https://www.codegrid.net/articles/2020-vue3-1

## 初期設定〜アプリの作成まで
[公式リポジトリ](https://github.com/vuejs/vue-next)のREADMEを参考に設定しました。

### アプリの作成

```bash
# Vue-cliがインストールされていない場合は↓でグローバルインストール
npm install -g @vue/cli # OR yarn global add @vue/cli

vue create [アプリ名]
```

特になければ`vue 3 preset`を選択。
※勿論Vue 2と同じく`Manual install`を選択し、下記の画像のように全部盛りにすることも出来ます。
![スクリーンショット 2021-10-10 15.11.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919803/f1c04790-77e8-e977-db28-ebfdf8f798bd.png)

そしてnpm/yarnのインストールが完了してから、`npm run serve` or `yarn serve`すると、Vue 3アプリが立ち上がるはずです。

なおVue 3は上記のVue cliを使う以外にViteを使って作成することも出来ます。

### VSCode拡張機能インストール
Vue3で使用するVSCodeの拡張機能は`Vetur`ではなく`Volar`が推奨されています。
そのため`Vetur`を入れている場合、こっちはDisable（無効化）してください。

https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar

### devtoolsのインストール
devtoolsが**beta版**でないと3系に対応していないのでインストール＆有効にします。
（安定版を入れている場合は安定版の方を無効にする）

https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg?hl=ja

## Composition APIとは
<公式ドキュメント>
https://v3.ja.vuejs.org/guide/composition-api-introduction.html

Vue 2まで馴染みのあったコンポーネントの書き方は`Options API`と呼ばれるものでした。

```ts
// Options API

<script lang="ts">
import Vue from "vue";
import HelloWorld from "@/components/HelloWorld.vue";

interface DataType {
  count: number
  initilize: boolean
}

export default {
  name: "Home",
  data():DataType {
    return {
      count: 0,
      initilize: false
    }
  },
  computed: {
    message() {
      return `Count is ${this.count}`;
    }
  }
  methods: { ... },
}
</script>
```

ただし、この書き方はdata、computed、methodsといった宣言があるため、コンポーネントが持つロジックが大きくなるほど肥大化し、処理が追いにくくなる問題がありました（大規模アプリケーションだと尚更）。
そこでVue 3ではこうした問題に対処するため、`Composition API`が登場しました。

```vue
// Composition API

<script lang="ts">
import { computed, reactive, onMounted, defineComponent } from "vue";
import HelloWorld from "@/components/HelloWorld.vue";

export default defineComponent({
  name: "Home",
  components: {
    HelloWorld,
  },
  setup() {
    const data = reactive({ count: 0, initilize: false });
    const message = computed(() => {
      return `Count is ${data.count}`;
    });
    return {
      data,
      message,
    };
  },
});
</script>
```

ただし、`Composition API`が強制されているわけではなく、**Options APIもVue 3では引き続き使用可能です**。ケースバイケースで使い分けることが出来ます。

`Composition API`の大きな変化かつ利点として、「コンポーネント特有のロジックを別ファイルに切り出すこと」が出来るようになりました。
このように切り出された処理は`コンポジション関数（Composition Function）`と呼びます。
（Reactをご存知の方はReact hooksに近いものと思っていれば大丈夫です）

これによって以下の恩恵が得られます。アプリケーション開発の規模が大規模になればなるほどこの恩恵はでかいでしょう。
  
- 該当ロジックが別ファイルに切り出されることによって、コンポーネントのコードが整理されて見やすくなる
- 同じロジックを複数のコンポーネントに何度も書く必要がなくなった

なお、定義するコンポジション関数の名前などは何でもいいですが、以下の形で書かれることが多いです。

- `src/composable`フォルダ以下に定義したファイルを設置
- 関数名を`useXXX`にする
- 拡張子は`js`もしくは`ts`

以下コンポジション関数の記載例となります。

```ts
// コンポジション関数<useUserNames>を定義
import { computed, ref } from 'vue'

export const useUserNames = () => {
  const userNames = ref<string[]>([])
  const getUserNames = async() => {
    userNames.value = await fetchUserNames()
  }
  const resultString = computed(() => {
    if(userNames.value.length === 0) {
      return 'No User Names'
    }
    return 'User Names have'
  })
  return {
    userNames,
    getUserNames,
    resultString
  }
}
```

```vue
// 定義したコンポジション関数を使ってコンポーネント側に表示
<template>
  <p>UserNames</p>
  <div v-for="userName in userNames">
    {{ userName }}
  </div>  
</template>

<script lang="ts">
import { computed, reactive, onMounted, defineComponent } from "vue";
import { useUserNames } from '@/composable/useUserNames'

export default defineComponent({
  name: "UserNames",
  async setup() {
    const {userNames , getUserNames, resultString} = useUserNames()
    await getUserNames()
    return {
      userNames,
      resultString,
    };
  },
});
</script>
```

## Fragments
またVue 3ではもう一つ大きな新機能として`Fragments`が登場しています。

<公式ドキュメント>

https://v3.ja.vuejs.org/guide/migration/fragments.html

Vue 2までは以下の例のようにコンポーネントのtemplateタグには一つしか入れ子を入れられませんでした。
そのため余分なdivタグを入れて対処しなければいけない状況が発生していました。

```vue
<!-- Vue 2までの書き方 -->
<template>
  <div>
    <h1>example</h1>
    <p>vue 3 example</p>
    <div>...</div>
  </div>
</template>
```

Vue 3ではtemplateタグに複数の入れ子を入れることが可能になり、余分なdivタグを入れる必要が
なくなり、テンプレートが見やすくなりました。

```vue
<!-- Vue 3で可能になった書き方 -->
<template>
  <h1>example</h1>
  <p>vue 3 example</p>
  <div>...</div>
</template>
```

## サンプルコード/見たほうがいいリポジトリ
Vue 3で実際に実装した場合の例として、今回は「PokeAPI」を使ったサンプルコードを載せておきます。

https://github.com/miily8310s/vue3-sample-app

またここのリポジトリもVue 3の機能がほぼすべて盛り込まれており、かなり参考になります。

https://github.com/mutoe/vue3-realworld-example-app

## もっとVue 3の理解を深めたい
今の所いざ業務などで本格的に使うようになったときに備えて、以下に最低触れておこうと考えています。

### Design Patterns for Vue.js
Vue Test Utilsのメンテナーであり、[Vue Testing Handbook](https://lmiller1990.github.io/vue-testing-handbook/)の作者のLachlan Miller氏の本。

https://lachlan-miller.me/design-patterns-for-vuejs/

### Vue JS 3: The Composition API
同じくLachlan Miller氏のUdemyコース。
今回の記事では触れませんでしたが、`Teleport`と`Suspense`機能の知見がまだまだ甘いので、ここでキャッチアップしておこうと思っています。

https://www.udemy.com/course/vuejs-3-the-composition-api/

その他Nuxt.jsのバージョン3やVuexバージョン5も今後広まっていくと思うので、リリースされたタイミングでしっかりキャッチアップしておこうと思っています。（Githubの公式リポジトリにも貢献していきたかったり）