Nuxt + Composition-APIの導入手順とはじめかた

# Nuxt + Composition-APIの導入手順とはじめかた
## はじめに

Vueは、JavaScript製のUIフレームワークです。そのVueについてもう少しWebサイト構築に便利なようVue-routerやVuexなどをまとめたのがNuxtになります。つまるところNuxtというのはフレームワークのフレームワークになります。

Nuxtは非常に便利なのですが、残念ながら今はVueのメジャーバージョンのアップデート時期ということもありいささか混乱している状況です。おそらく他のQiitaの記事を読んでも「書きかたが全然違う……」ということもありえますが、今後新しい書き方が一般的になるということで、composition-apiを使用した書き方を紹介したいと思います。

## 対象読者

- ある程度JavaScript/TypeScript、Nodejsがわかる方
- Vueちょっとわかる方
- Composition APIが初めてという方



## 環境

以下はインストールしておく必要があるものです。

- [Nodejs](https://nodejs.org/ja/)
- [Yarn](https://classic.yarnpkg.com/ja/) (※必ず必要というものではありませんが、Yarnインストールされている前提で説明します)

## インストール

Nuxtが開発しているCLIのcreate-nuxt-appから簡単にNuxtアプリが作れます。
nuxtをそのままインストールすることもできますが、基本的にはcreate-nuxt-app経由で作ることがほとんどです。

```
yarn create nuxt-app project-name

# または
npx create-nuxt-app project-name
```

project-nameには今回作るアプリの名前を入れます。



```sh
✨  Generating Nuxt.js project in project-name
? Project name: project-name
? Programming language: TypeScript
? Package manager: Yarn
? UI framework: None
? Nuxt.js modules: Axios
? Linting tools: ESLint, Prettier
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
```

CLIから対話的に選択項目を色々と聞かれますが、今回の開発に必須なのはTypeScriptであることとだけです。
上記ではついでにESLint+Prettier+Axiosモジュールを入れていますが、必須ではありません。
インストールが終わったら`cd project-name`でプロジェクトディレクトリに入り、以下のコマンドを打ってください。

```
yarn dev

# またはyarnをインストールしていない場合
npm run dev
```

Nuxtの開発モードで開始します。デフォルトではhttp://localhost:3000でリッスンしていますので、アクセスして正常にNuxt初期画面が出ればOKです。

## Composition APIをインストール

次にComposition APIをインストールします。

```sh
yarn add @vue/composition-api
```

plugins/composition-api.tsを用意します。

```TypeScript:plugins/composition-api.ts
import Vue from 'vue'
import VueCompositionApi from '@vue/composition-api'

Vue.use(VueCompositionApi)
```

nuxt.config.jsにプラグインとして登録します。

```JavaScript
plugins: [
  '@/plugins/composition-api'
],
```

これで使用したいVueファイルなどで以下のように宣言すればcomposition-apiが使えます。

```
import { ref } from '@vue/composition-api'
```





## リアクティブシステムを使ってみる

早速リアクティブシステムを使ってみます。

```vue
<template>
  <div>{{ count }}</div>
</template>
<script lang="ts">
import { ref } from '@vue/composition-api'
export default {
  setup() {
    const count = ref(1)
    return { count }
  },
}
</script>
<style></style>

```

Vueの基本的なファイルは、テンプレートブロックとスクリプトブロック、スタイルブロックの３つに分けられます。
テンプレートには主にhtml要素を書いていきます。スクリプトブロックではJavaScript/TypeScriptを書いていきます。
今回はTypeScriptを使用するので、scriptタグのプロパティで言語を以下のように指定します。

```html
<script lang="ts"></script>
```

テンプレートブロック内でデータバインディングしたい際は、ムスターシュ構文({{}}記号で変数を囲むような構文)で可能です。

### リアクティブ用関数について

Composition APIで変数をリアクティブにするにはref()とreactive()関数の２つを使用することができます。
どちらもリアクティブにする関数で、どっちがいいかと言われると、どっちも両方使えたほうが良いので丸暗記してほしいです。最初はrefから覚えるといいと思います。

```typescript
const count = ref(1)
```

これで初期値1のリアクティブ変数を作れます。
今回は`ref`に`1`という値を渡していますので、勝手にnumber型と推論されていますが、もし渡したい変数の型を明確にしたい場合は、以下のように型引数を渡します。

```typescript
const count = ref<number>(0)
```

基本的には型引数がない場合は型推論されるので、単純な数字や文字列の場合はあまり気にせず使用します。
型注釈も含めて書きたい場合は以下のようにします(普段はこのようには書いてませんが)。

```typescript
import { Ref } from '@vue/composition-api'
const count:Ref<number> = ref<number>(0)
```



## 動的に変更を加える

次に、この数を変更するためのボタン要素とインクリメント関数を追加してみましょう。
インクリメントは以下のように関数にして、return でその関数を返します。

```typescript
export default {
  setup() {
    const count = ref(1)
    const increment = () => {
      count.value++
    }
    return { count, increment }
  },
}
```

または

```typescript
export default {
  setup() {
    const count = ref(1)
    function increment() {
      count.value++
    }
    return { count, increment }
  },
}
```

上の方が関数式。下は関数宣言によるものです。
どちらでも使えますが、関数式で作るほうが色々と便利なので、上の書き方をおすすめします。
returnは返り値を意味しますが、返り値は１つのオブジェクトです。
基本的にJavaScript/TypeScriptは１つの値しか返せません。もしも複数の要素を返したい場合によく使われるのは、複数の変数を１つのオブジェクトにまとめることです。

```
return { count: count, increment: increment }
```

この書き方はES6以降の書き方で、以下のように省略しできます。

```
return { count, increment }
```


プロパティ名とその値の変数名が同じ場合は、１つにまとめることができます。
テンプレートブロック内で使いたい変数をオブジェクトのプロパティにすればいいので、例えば以下のような書き方でも普通に使用できます。

```vue
<template>
  <div>
      {{numberOne}}<br />
      {{numberTwo}}<br />
      {{numberThree()}}<br />
  </div>
</template>
<script lang="ts">
export default {
    setup(){
        return { 
            numberOne: 'いち', // 文字リテラル
            numberTwo: 4/2, // 計算式
            numberThree: () => 'さん' //関数式。()=>{ return 'さん'}と同じ
        }
    }
}
</script>
```

あとはテンプレートブロックに、ボタン要素とクリックイベント発火用のディレクティブを追加すればOKです。

```vue
<template>
  <div>
      <button @click="increment">
          {{count}}
      </button>
  </div>
</template>
```

`v-on:click`ディレクティブの省略形である`@click`で、先程returnしたincrementを指定しています。これでクリックされたとき、incrementが実行されます。
まとめると以下のようになります。

```vue
<template>
  <button @click="increment">
    {{ count }}
  </button>
</template>
<script lang="ts">
import { ref } from '@vue/composition-api'
export default {
  setup() {
    const count = ref(1)
    const increment = () => {
      count.value++
    }
    return { count, increment }
  },
}
</script>
<style></style>

```

実際にボタンをクリックすると、数がカウントアップされれば成功です。

## 次回

次回からはCompositionAPIの追加機能など紹介したいと思います。