nuxt.jsでsessionStorageを使ってみました。

#はじめに
ユーザーがformを入力する際にミスでブラウザーを更新した場合入力したデータが消えてしまい入力し直さないといけないので、最悪の場合は離脱の要因になる可能性があります。ページを更新してもデータを残せるのが`sessionStorage`です。
[参考ページ](https://jp.vuejs.org/v2/cookbook/client-side-storage.html)

##目次
1. セッションストレージの使い方
2. JSON形式でGET ,SET
3. 入力値のformData削除
4. 終わり


##1.セッションストレージの使い方
簡単なhtmlを作成しdataとinputを紐付ました。`sessionStorage`を値をロードするために`mounted()`紐付けたinputのmodelを`getItem()`で囲んで定義する必要があり、`methods`には`key`と`value`を`setItem()`に定義し入力値が変わるのを監視するため`input`に`@change`methodをかけてました。


```.js
<template lang="pug">
   .container
      form
        .inputBox
           input(
            type='text',
            v-model='name'
            @change='set();'
          )
        input.submitBtn( type="submit" ) 送信
</template>
<script>
export default {
  data(){
    return{
      name: ''
    }
  },
  mounted(){
    if(sessionStorage.getItem('name')){
      this.name = sessionStorage.getItem('name');
    }
  },
  methods:{
    set: function(){
      sessionStorage.setItem('name',this.name)
    },
  }
}
</script>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611034/c05cf10f-369b-2e66-a787-202916383fcc.png)
上記のように値が入りました。
ただし、上記のように設計をすると例えばmailのinputやtelのinputなどが追加された場合下記のように追加をしないといけなくなります。

```.js
  mounted(){
    if(sessionStorage.getItem('name')){
      this.name = sessionStorage.getItem('name');
    }
    if(sessionStorage.getItem('email')){
      this.name = sessionStorage.getItem('email');
    }
  },
  methods:{
    set: function(){
      sessionStorage.setItem('name',this.name);
      sessionStorage.setItem('email',this.email);
    },
  }
```
inputが追加されるたび修正の手間発生すので自分はJSON形式で一括保存をするようしたいと思います。

##2.JSON形式でGET ,SET
追加されるinputに親を付けていく感じです。

```.js
export default {
  data(){
    return{
　　　　//親
       formDatas : { 
　　　　　　//formDatasの子
          name : '',　
          email : ''
       }
    },
  }
</script> 
```
htmlには`v-model='name'`にした部分を`v-model='formData.name'`親をつけて紐づける作業が必要です。

```.js
<template lang="pug">
   .container
      form
        .inputBox
           nput(
            type='text',
            v-model='formData.name'
            @change='set();'
          )
         .inputBox
           input(
             type='email', 
             v-model='formData.email'
             @change='set();'
          )
        input.submitBtn( type="submit" ) 送信
</template>
```
JSON形式で`get` `set`するためには`JSON.parse()`と`JSON.stringify()`のmethodが必要です。

`JSON.parse()`の引数にJSONデータを指定して、オブジェクトデータに変換して`JSON.stringify()`でfomDataの値をJSONデータにする役割です。


コードは下記のようになりました。

```.js
mounted(){
    if(sessionStorage.getItem('formDatas')){
        this.formDatas = JSON.parse(sessionStorage.getItem('formDatas'));
    }
},
methods: {
    set: function() {
        sessionStorage.setItem('formDatas',JSON.stringify(this.formDatas))
    }, 
},
```


fomDataのkeyにvlueをJSON形式で保存するイメージです。
inputに入力したら下記のようにJCON形式で保存されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611034/ee058dd5-e665-0095-99b3-5efe638f6e6e.png)

##3.formData削除
処理が終わったら`sessionStorage`に保存されているdataは必要ではないので削除します。
簡単に実行できるのが下記のコードだけでクリアになります。

```.js
sessionStorage.clear()
```
このクリア関数を送信methodに入れるのもありですがthanksページで実行する方が個人的には一番簡単かと思いました。

完成コードは下記です。

```.js
<template lang="pug">
   .container
      form
        .inputBox
           nput(
            type='text',
            v-model='formData.name'
            @change='set();'
          )
          .inputBox
            input(
              type='email', 
              v-model='formData.email'
              @change='set();'
          )
        input.submitBtn( type="submit" ) 送信
</template>

<script>
export default {
  data(){
    return{
       pageName: 'contact',
       formDatas : {
            name : '',
            mail : ''
       }
    },
    mounted(){
      if(sessionStorage.getItem('formDatas')){
            this.formDatas = JSON.parse(sessionStorage.getItem('formDatas'));
        }
    },
    methods: {
      set: function() {
        sessionStorage.setItem('formDatas',JSON.stringify(this.formDatas))
      }, 
    },
  }
</script>
```
##4. 終わり
ユーザー側でinputに入力をして、もしミスなどでページを更新をした場合入力値を残せる`sessionStorage`を実装してみました。

##追加
セッションストレージを使ってページをステップを分けて`threeStep`まで分けたい場合`oneStep`を入力してないのにもし`twoStep`アクセスする場合正式なアクセスではないのでその場合はセッションストレージをチェックしてリダイレクトをさせることも可能です。
[参考ページ](https://stackoverflow.com/questions/16010827/html5-localstorage-checking-if-a-key-exists)


```.js
mounted(){
　　//formDatasを割当
   let formComponent = JSON.parse(sessionStorage.getItem('formDatas'))
　　//formDatasのnameチェックしnullか空いている場合
   if (formComponent.name === null || formComponent.name === '') {
　　　　　//指定先にリダイレクト
   　　　location.href='リダイレクト先'
   }
}

```
セッションストレージの`formDatas`のどれかをチェックして`null`か`''`空いている場合はリダイレクトをさせる処理です。
formをthreeStepで分ける場合twoStepとthreeStepに記載すればそのtwoStepとthreeStepのURLが直で打ち込まれた場合`mounted()`を先に読まれるので指定されたリダイレクト先に移動されると思います。

##スマートな書き方
２ページ以上使うので共通化にしたいためMixin定義をします。

```Mixsins.js
export const empty = {
    methods: {
        empty( str ) {
            return str === null || str == '' ;
        },
        isCompletedOneStep() {
            var formComponent = JSON.parse(sessionStorage.getItem('formDatas'));
            return !this.empty(formComponent.name);
        },
    }
}

```
twoStepとthreeStepの`mounted()`に関数をif文に定義すれば同じ処理になるので`isCompletedOneStep `意味だけわかれば可読性の高なりコードの量も減ります。

```.js
mounted(){
    if( !this.isCompletedOneStep() ){
         alert('正式なアクセスではありません。')
         location.href='リダイレクト先'
        }
    },
```
以上です。