フォームの値をキャッシュできるkeep-aliveを使ってみた（Vue.js / Nuxt.js）

# はじめに

登録フォームと入力確認フォームで、次の画面に進んで「やっぱ戻る！」となった時でも値がキャッシュされるようにできたのでその方法をこちらに記載します。

現在作成中のサービスで動作確認を行っていますので、ビジュアル的にイマイチなところはご了承くださいm(_ _)m

# keep-aliveを使う
フォームの値をキャッシュする時に便利な仕組みがあります。
使い方は公式ドキュメントにわかりやすい例がのっています。
今回はそれを自分のサービス内で使ってどう書いたか、というところを説明します。
[動的 & 非同期コンポーネント - Vue.js](https://jp.vuejs.org/v2/guide/components-dynamic-async.html)

### まず動的コンポーネントとは？

> 動的なコンポーネントとは、ユーザーの操作やアプリケーションの状態によって、コンポーネントを切り替える仕組みです。
動的コンポーネントを使用すると、例えばタブ付きのインターフェースを持つアプリケーションで、タブがクリックされた時にタブページに表示されるコンポーネントを切り替えることができます。

[コンポーネントを動的に切り替える 要素 [Vue.js]](https://johobase.com/vue-js-dynamic-component/#:~:text=%E3%82%92%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%99%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-,%E5%8B%95%E7%9A%84%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88,%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)

つまり、何らかの操作や変化が加わった際に状態を変えるコンポーネントのことだと理解しました。Vueでよくある書き方だとv-ifやisなどでしょうか。

次で実際に書いたコードを見ていきます。

# keep-aliveを使ったコードの全体像

まずコードの全体像を貼り、その後keep-aliveを使った場合と使わなかった場合の違いを説明します。

<br>
こちらのフォームを構成する要素は3つ。

メインとなる`registration.vue`のページと、`FormListInput` コンポーネント、 `FormListConfirm`コンポーネントです。FormListInput は入力フォーム、FormListConfirm は登録が完了しましたと告げるページです。


```pages/registration.vue
<template>
   <div>
       <keep-alive>
          <form-list-input v-if="formNumber === 0" />
          <form-list-confirm v-if="formNumber === 1" />
       </keep-alive>
       <button v-if="formNumber === 0" @click="plusNum">次へ</button>
       <button v-if="formNumber === 1" @click="minusNum">戻る</button>
   </div>
</template>

<script>
import FormListInput from '../../components/FormListInput.vue'
import FormListConfirm from '../../components/FormListConfirm.vue'

export default {
  components: {
      FormListInput,
      FormListConfirm,
  },
  data(){
      return {
          formNumber: 0,
      }
  },
  methods: {
      plusNum() {
          this.formNumber ++;
      },
      minusNum() {
          this.formNumber --;
      }
  }

}
</script>
```

<br>

```components/FormListInput.vue
<template>
    <div>
        <h1>チームを登録する</h1>
        <label for="チーム名">チーム名：</label><input type="text" v-model="name">
        <label for="チーム名">競技レベル：</label><input type="text" v-model="level">
        <label for="チーム名">活動場所：</label><input type="text" v-model="area">
    </div>
</template>

<script>
export default {
    data(){
        return {
            name: "",
            level: "",
            area: "",
        }
    },
}
</script>
```

<br>

```components/FormListConfirm.vue
<template>
    <div>
        <h1>登録内容を確認する</h1>
    </div>
</template>
```

# コードの詳細

ここでkeep-aliveを使った場合と使わなかった場合を比べます。


###keep-aliveを使わなかった場合

```jsx
<template>
    <div>
      <form-list-input v-if="formNumber === 0" />
      <form-list-confirm v-if="formNumber === 1" />
      <button v-if="formNumber === 0" @click="plusNum">次へ</button>
      <button v-if="formNumber === 1" @click="minusNum">戻る</button>
    </div>
</template>

...省略
```

※下記画像に表示される「フォーム番号：0」のコードは消してありますので気にしないでください。

<br>
**フォームを入力する**
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230656/621b416b-e20d-76be-5888-5fd21d45247f.png)


**次へボタンで画面が切り替わった**

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230656/7112b3cb-fb97-d3c4-ccd6-a730342be332.png)


**ここで戻るボタンを押すと入力した値が消えている**

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230656/d9e7a73e-0734-9aa2-67f5-cb4a4b329c82.png)



###keep-aliveを使った場合

```jsx
<template>
   <div>
       <keep-alive>
          <form-list-input v-if="formNumber === 0" />
          <form-list-confirm v-if="formNumber === 1" />
       </keep-alive>
       <button v-if="formNumber === 0" @click="plusNum">次へ</button>
       <button v-if="formNumber === 1" @click="minusNum">戻る</button>
   </div>
</template>
```

<br>
**フォーム入力**

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230656/28bca028-9695-31a7-aab8-cf0c2906e892.png)


**確認画面へ**

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230656/ae9eb5ca-18a7-b274-a53a-9e7ce1b57f3c.png)


**戻るを押しても値が保持されていることがわかる**

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230656/8c0645f5-2a46-662d-9b38-6a1e48b43a10.png)


# さいごに

keep-aliveタグで囲むだけで入力値のキャッシュができるのはとても便利です。ただこの方法だとまだブラウザバックに対応しきれていないのでそこの対応は別途必要になります。