MailAddressとPasswordによるユーザー新規登録/認証【Vue.js/Vuetify/Vuex/Firebase】

#概要
・　ポートフォリオでメールとパスワードでユーザー新規登録/認証機能を実装したので、コメントつきのソースコードを紹介
・　使用した技術はRealtimeDatabase（Firebase）・Vuetify・Vue.js・Vuex
・　開発環境はVue-Cli

```csharp:signup.vue
<template>
   　　　<div>
    　　　　<h1>新規登録</h1>
             <v-divider></v-divider>
             //下記の「type="submit"」のクリックにより、下記に入力したemailとpasswordを引数としてonSignupメソッドが発動
             <form @submit.prevent="onSignup">
             <v-layout>
                  <v-flex>
                     <v-text-field
                        name="email"
                        label="Mail"
                        id="email"
                        v-model="email"
                        type="email"
                        required>
　　　　　　　　　　　　　</v-text-field>
                 </v-flex>
             </v-layout>
             <v-layout>
                   <v-flex>
                      <v-text-field
                        name="password"
                        label="Password"
                        id="password"
                        v-model="password"
                        type="password"
                        required>
                      </v-text-field>
                   </v-flex>
              </v-layout>
              <v-layout>
                   <v-flex>
　　　　　　　　　　　　　//クリックすると<form></form>間に入力した情報が提出（submit）される
                      <v-btn type="submit">
                      </v-btn>
                   </v-flex>
              </v-layout>
           </form>
     　</div>           
</template>

<script>
export default {
  data(){
      return{
      //入力したメールアドレス
      email: "",
      //入力したパスワード  
      password: ""
    }
  },
  computed: {
    //あなたのユーザー情報を取得
    user(){
      return this.$store.getters.user
    }
  },
  watch: {
　　//あなたのユーザー新規登録処理が成功したらホーム画面へ遷移する
    user(value){
      if(value !== null && value !== undefined){
        this.$route.push("/")
      }
    }
  },
  methods: {
　　//v-modelで入力したemailとpasswordを引数にしてactionsの"signUserUp"へデータを渡す
    onSignup(){  
      this.$store.dispatch("signUserUp", {email: this.email, password: this.password})
    }
  }
}
</script>


```

```csharp:store
state: {
　//あなたのユーザー情報のstate。ログインするとユーザー情報のオブジェクトがnullに入る
  user: null
},
mutations: {
 //stateのuserをactionsのユーザーオブジェクトにする。またはnullに戻す
 setLoginUser(state, payload){
     state.user = payload
   }
},
actions: {
  signUserUp({commit}, payload){
　　　　//dispatchで引数にしたemailとpasswordを使って、firebaseのAuthenticationsにユーザーアカウントが作成される。
      firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
       .then(
         user => {
　　　　　　//登録済みユーザーオブジェクト
          const newUser = {
            id: user.uid
           }
　　　　　　 //mutationsへ登録済みユーザーオブジェクトを渡す
           commit("setLoginUser", newUser)
         })
       .catch(
         error => {
           console.log(error)
         })
    }
},
getters: {
　 //stateのユーザーオブジェクトをgettersで取得
   user(state){
     return state.user
  }
}
```
#ユーザー新規登録の大まかな処理フロー
①　v-modelのアドレスとパスワードを入力し、引数としてonSignupメソッドが動き、actionsのsignUserUpが動く。

②　actionsでのcreateUserWithEmailAndPasswordにてFirebaseのAuthenticationsにアドレスとパスワードを新規登録。登録成功したら、そのユーザーオブジェクトをmutationsへ渡す。
※　Promise(.then/.catch)を付けないと、ユーザーのアドレスとパスワードがAuthenticationsに登録される前にuser情報がnullのままmuationsへ処理が進んでエラーになるので、Promiseは忘れないように。 Promiseについては、下記の記事がわかりやすく、参考にさせていただきました。
　　https://qiita.com/saka212/items/9b6cfe06b464580c2ee6　

③　mutationsによって、stateでnullになっているuserにmutationsのユーザーオブジェクトを上書きする。

④　signup.vue にてgettersでstateのユーザーオブジェクトを引っ張ってきて、watchにて「gettersのuserにユーザーオブジェクトが入ってきてユーザー新規登録が完了したら、ホーム画面に戻る」　ように監視する。

⑤　新規ユーザー登録完了した後
、ホーム画面に戻ることで完了

では次に新規登録したユーザー情報のメールアドレスとパスワードでログインするフローについて。


```csharp:signin.vue
<template>
    <div>
       <h1>ログイン画面</h1>
　　　　 //下記の「type="submit"」のクリックにより、下記に入力したemailとpasswordを引数としてonSigninメソッドが発動
       <form @submit.prevent="onSignin">
       <v-layout>
         <v-flex xs12>
            <v-text-field
            name="email"
            label="Mail"
            id="email"
            v-model="email"
            type="email"
            required>
　　　　　　　</v-text-field>
         </v-flex>
       </v-layout>
       <v-layout>
         <v-flex xs12>
            <v-text-field
            name="password"
            label="Password"
            id="password"
            v-model="password"
            type="password"
            required></v-text-field>
         </v-flex>
        </v-layout>
        <v-layout>
         <v-flex>
　　　　　　//クリックすると<form></form>間に入力した情報が提出（submit）される
           <v-btn type="submit">
            ログインボタン
           </v-btn>
         </v-flex>
        </v-layout>
      </form>
    </div>
</template>

<script>
export default {
  data(){
      return{
　　　 //入力したメールアドレス
      email: "",
　　　 //入力したパスワード
      password: ""
    }
  },
  computed: {
　　 //あなたのユーザー情報を取得
    user(){
      return this.$store.getters.user
    }
  },
  watch: {
    //あなたのユーザーログイン処理が成功したらホーム画面へ遷移する
    user(value){
      if(value !== null && value !== undefined){
        this.$route.push("/")
      }
    }
  },
  methods: {
　  //v-modelで入力したemailとpasswordを引数にしてactionsの"signUserIn"へデータを渡す
    onSignin(){  
      this.$store.dispatch("signUserIn", {email: this.email, password: this.password})
    }
  }
}
</script>
```
```csharp:store.js
state: {
  //あなたのユーザー情報のstate。ログインするとユーザー情報のオブジェクトがnullに入る
  user: null
},
mutations: {
  //stateのuserをactionsのユーザーオブジェクトにする。またはnullに戻す
  setLoginUser(state, payload){
      state.user = payload
    }
},
actions: {
  signUserIn({commit}, payload){
      //dispatchで引数にしたemailとpasswordを使って、firebaseのAuthenticationsにて認証
      firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
       .then(
　　　　　 //ユーザーのオブジェクト
         user => {
           const newUser = {
            id: user.uid
           }  
　　　　　　 //mutationsへログインするユーザーオブジェクトを渡す
           commit("setLoginUser", newUser)
         })
       .catch(
         error =>{
           console.log(error)
         })
    },
}
```
#ユーザー認証処理のフロー：　新規登録処理とほぼ同じ流れ
①　v-modelのアドレスとパスワードを入力して引数としてonSigninメソッドが動き、actionsのsignUserInが動く。

②　actionsでのsignInWithEmailAndPasswordにてFirebaseのAuthenticationsにアドレスとパスワードを認証。認証成功したら、そのユーザーオブジェクトをmutationsへ渡す。

③　stateでnullになっているuserにmutationsのユーザーオブジェクトを上書きする。

④　signin.vue にてgettersでstateのユーザーオブジェクトを引っ張ってきて、watchにて「gettersのuserにユーザーオブジェクト入りユーザー認証が完了したら、ホーム画面に遷移する」　ように監視する。

⑤　ユーザー認証が完了し、ホーム画面に戻ることで完了

#最後に
今回は自分なりに書きやすいPromiseでコードを書きましたが、async/awaiteもそろそろ使用してコードを書くことにもチャレンジしていこうかと思います。
できるだけ端的にまとめましたが、もし上記のフローでの理解に誤りがあったり、より良い表現などあればコメントいただければ幸いです。