Nuxt3で簡単なToDoアプリを作っていく 〜フォーム入力バインディング〜

## 概要
Nuxt3がすごいらしいので、ToDoアプリを作りながら学んでいきたいと思います。
内容はVue.js初心者向けになってます。

### 前回の記事
https://qiita.com/nishikor/items/4737bd987674dab34139

## この記事のゴール
フォーム入力バインディングを使った動作の確認ができる

## 完成コード
先に完成コードを載せておきます。

```app.vue
<template>
  <div>
    <input v-model="taskName">
    <p>{{ taskName }}</p>
  </div>
</template>

<script setup lang="ts">
const taskName = ref<string>('');
</script>
```

## 前提
本来であれば、pagesディレクトリを用意して進めていきたいですが、ルーティングに関しては別記事にします。
そのため、今回はapp.vueに記述していきます。

### スタイルルール
vueファイルは3つのトップレベル属性で構成されます。
この記事では、特に指定がない限り以下の順で記述しています。
- `template`
- `script`
- `style`

vue２時点での公式のスタイルガイドです。

https://jp.vuejs.org/v2/style-guide/index.html#%E5%8D%98%E4%B8%80%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E3%83%88%E3%83%83%E3%83%97%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AE%E5%B1%9E%E6%80%A7%E3%81%AE%E9%A0%86%E5%BA%8F-%E6%8E%A8%E5%A5%A8

## 書いていく
### scriptの準備
vue3から導入されたscript setupを使用して、コードを書いていきます。
言語はTypeScriptです。
```app.vue
<script setup lang="ts">
</script>
```
まず、Nuxt2、Composition APIと違いこれでscriptを記述していく準備が完了です。
必要な属性のインポートも`export default defineComponent`も必要ありません。
これだけで開始できる！素敵！

### リアクティブ変数の準備
リアクティブとは、対象プロパティが変更されるたびに検知して、自動的に画面（view）に反映することです。

https://ja.vuejs.org/guide/essentials/reactivity-fundamentals.html

```app.vue
<script setup lang="ts">
const taskName = ref<string>('')
</script>
```
refによって、`taskName`がリアクティブとなります。
Composition APIの場合、refを使用する際はimportして読み込む必要がありましたが、Nuxt3ではその必要がありません。
また、`setup()`内で`return`の必要がありましたがその必要もなくなりました。
上記の定義だけで`template`内で読み込むことができます。

<details><summary>Nuxt2、Composition APIの場合</summary>

``` sample.vue
<script lang="ts">
import { defineComponent, ref } from '@nuxtjs/composition-api'
export default defineComponent({
  setup() {
    const taskName = ref<string>('')
    return {
      taskName,
    }
  },
})
</script>
```
</details>

### フォーム入力バインディング
フォーム入力バインディングとは、template(HTML)の入力要素と、対応するリアクティブ要素の状態を同期することです。
先ほど作成した、`taskName`が同期されているかを確認します。
```app.vue
<template>
  <div>
      <input v-model="taskName">
      <p>{{ taskName }}</p>
  </div>
</template>
```

`<input v-model="taskName">`を用意します。
`v-model`はinput要素のvalueプロパティとinputイベントと結びついています。
input要素に値が入力される→valueが書き変わる→inputイベントが発火する→taskNameが書き変わる→input要素のvalueとtaskNameが同じ状態

そのため、taskNameはインプット属性のvalueと結びつき、入力を行うとすぐさま画面に反映されます。
![フォーム入力バインディング.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639493/879d953f-596f-9199-2c81-a4e41ea5c285.gif)

### リアクティブではないとき
scriptを以下のように変更してみます。
リアクティブをやめ、初期値として「Hello Composition API」としておきます。
templateはそのままです。
```app.vue
<script setup lang="ts">
const taskName = 'Hello Composition API';
</script>
```
先ほどとは異なり、「Hello Composition API」が初期値としてinput要素、pタグに入力されています。
しかし、リアクティブではないため、input要素を変更しても、pタグには反映されません。
![非リアクティブ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639493/4d85ac32-5e57-bca0-5505-b0cf0a733ca6.gif)
フォームに入力された値が画面に反映されないような時は、設定した変数がリアクティブであるか否かを疑いましょう。

## まとめ
Nuxt2に比べて記述量が減り、ネストが浅くなりそうです。
import不要、defineComponent不要というのは、小さなストレスがなくなったように思います。
今回は動きを確認する程度だったので、Vue.js初心者向けの内容になってしまいました。
次回はイベントハンドリングとリストレンダリングについてを予定しています。

https://qiita.com/nishikor/items/3ca4c42d14edecd5a06f