Firebase+Vue.js(Vue2 Options API)でログイン/サインアップフォームを作成する

2021年4月23日Vue.js

ログインフォーム
Firebase+Vue.js(Vue2 Options API)でログイン/サインアップフォーム作成する方法です。

Firebase+Vue.js(Vue3 Composition API)でログイン/サインアップフォーム作成する方法は次の記事を参考にしてみてください。

作成するフォーム

ログイン失敗
ログインとサインアップ(アカウントの新規作成)の機能があり、ログインやサインアップに失敗するとエラーメッセージが表示されます。

ダッシュボード
登録するとダッシュボードに飛んで、ログインとサインアップは非表示となり、代わりにログアウトが表示されるシンプルなフォームです。

CSSはBulmaフレームワークを使用しています。
こちらのソースコードでGithub上でコードを確認できます。

作成手順

    1. ターミナルでVueのプロジェクトを作成します。
      その際、必要なものを選択します。
      今回ルーターを使うのでrouterは選択しておきます。

      ? Please pick a preset: Manually select features
      ? Check the features needed for your project: Choose Vue version, Babel, Router
      ? Choose a version of Vue.js that you want to start the project with 2.x
      ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
      ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
      ? Save this as a preset for future projects? No
      
    2. そして作成したプロジェクトフォルダに移動してリモートリポジトリと接続します。
      リモートリポジトリとつなげるときのGitの流れに関しては次の記事を参照してみてください。
    3. Firebaseでバックエンド側のプロジェクトを作成します。
      Firebaseの基本的な使い方は次の記事を参考にしてみてください。
      firebaseフォルダを作成して、config.jsを作成します。その内容も上の記事で確認できます。
    4. BulmaなどUIフレームワークを使う場合はインストールします。
    5. ログインフォームを作成します。
      Login.vue、Signup.vue、ログインしたあとの飛び先のページ(ex. Dashboard.vue)などのvueファイルを作成します。
    6. ルーターを設定します。

ディレクトリ構造

ディレクトリ構造

firebase/config.js

// firebaseをimport ①/5
import firebase from 'firebase/app'
import 'firebase/auth'

// firebaseの構成をコピペ ②/5
const firebaseConfig = {
  apiKey: "APIキー",
  authDomain: "ドメインアドレス",
  projectId: "プロジェクトID",
  storageBucket: "ストレージバケット",
  messagingSenderId: "メッセージの送信者ID",
  appId: "appID"
};
// firebaseを初期化する ③/5→SignUp.vueに移動して使う
firebase.initializeApp(firebaseConfig)

// init servises
const projectAuth = firebase.auth()

export { projectAuth }

詳しくは上で紹介したFirebaseの使い方の記事で説明しています。
firebaseをインストールした後、firebaseと必要なもの、今回はauthをインポートします。
そして、firebaseからfirebaseConfigをコピペします。
その後firebaseを初期化します。
そして、authをエクスポートできるように変数に格納します。
そして、エクスポートします。

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
// viewsにコンポーネントを追加したらまずはインポート
import Signup from '../views/Signup.vue'
import Login from '../views/Login.vue'
import Dashboard from '../views/Dashboard.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  // viewsにコンポーネントを追加したら次にpathの設定→次にrouter-linkなどを設定、今回はApp.vue
  {
    path: '/signup',
    name: 'Signup',
    component: Signup
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: Dashboard
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

パスを設定します。
作成したvueファイルをインポートします。
そして、path、name、componentを登録します。

App.vue

<template>
  <div id="app">
    <nav class="navbar" role="navigation" aria-label="main navigation">
    <div class="navbar-brand">
      <a class="navbar-item" href="/">
        Title
      </a>
    </div>
      <div id="navbarBasicExample" class="navbar-menu">
        <div class="navbar-start">
          <router-link to="/" class="navbar-item">Home</router-link>
          <router-link to="/about" class="navbar-item">About</router-link>
            <!-- viewsにコンポーネントを追加したら最後にrouter-linkを設定などする -->
        </div>
        <div class="navbar-end">
          <div class="navbar-item">
            <!-- ログインしていないときのみ表示 -->
            <div class="field is-grouped" v-if="!isAuthenticated">
              <p class="control">
              <router-link to="/signup" class="button is-primary">アカウントを作成</router-link>
              </p>
              <p class="control">
              <router-link to="/login" class="button is-info">ログイン</router-link>
              </p>
            </div>
            <div class="field" v-else>
              <p class="control">
                <button class="button is-danger" @click="logout">ログアウト</button>
              </p>
            </div>
          </div>
      </div>
     </div>
    </nav>

  <router-view/>
  </div>
</template>
<script>
import { projectAuth } from './firebase/config.js'

export default {
  data () {
    return {
      isAuthenticated: false
    }
  },
    // authの状態を設定する3/3
  created() {
    projectAuth.onAuthStateChanged(user => {
      if(user) {
        this.isAuthenticated = true
      }
    })
  },
  methods: {
    logout() {
      projectAuth.signOut()
      .then(() => {
        this.isAuthenticated = false
        this.$router.push('/login')
      })
    }
  }
}</script>
<style scoped>
@import "../node_modules/bulma/css/bulma.css";
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}</style>

 

Bulmaフレームワークを使っているので、インストールした後、上のようにimportします。
templateではNavを設定しています。
ログアウトしたらログイン画面に飛んでほしいので、scriptではauthをインポートして、ユーザーが認証されている状態でないなら、logout()を実行してログイン画面にとばします。

Signup.vue

<template>
  <div>
    <div class="columns">
      <div class="column is-6 is-offset-3">
        <h1 class="title">アカウント作成</h1>
        <form @submit.prevent="signup">
          <!-- メール -->
          <div class="field">
            <div class="control">
              <input type="text" placeholder="Email" v-model="email" class="input">
            </div>
          </div>
          <!-- パスワード -->
          <div class="field">
            <div class="control">
              <input type="password" placeholder="Password" v-model="password" class="input">
            </div>
          </div>
          <!-- 送信ボタン -->
          <div class="field">
            <div class="control">
              <button class="button is-success">登録</button>
            </div>
          </div>

          <!-- エラー -->
          <article class="message is-danger" v-if="error">
            <div class="message-body">
              {{ error }}
            </div>
          </article>
        </form>
      </div>
    </div>
  </div>
</template>
<script>
// firebaseを使う importする④/5
// import firebase from 'firebase'
import { projectAuth } from '../firebase/config.js'

export default {
  name: 'Signup',
  data (){
    return {
      email: '',
      password: '',
      // authの状態を設定する1/2
      isAuthenticated: false,
      error: null,
    }
  },
  // authの状態を設定する2/2
  created() {
    projectAuth.onAuthStateChanged(user => {
      if(user) {
        this.isAuthenticated = true

        this.$router.push('/dashboard')

      }
    })
  },
  methods: {
    signup () {
      console.log('Sign up');

// firebaseを使う authを設定する⑤/5
      projectAuth.createUserWithEmailAndPassword(this.email, this.password)
      .catch(err => this.error = err.message)
    }
  }
}
</script>

今回はメールとパスワードだけのフォームを作成します。
templeteでは、メール、パスワード、送信ボタン、エラーが表示できるように設定します。
scriptでは、authをインポートして、ユーザーが新しくアカウントを作成できるようにします。
まずは、data()でメールとパスワードと認証状態とエラーの初期化をします。
そして、created()でauthを確認するためにonAuthStateChanged()を使って、ダッシュボードに飛ばせるようにrouterを設定します。
methodsでは、メールとパスワードでサインアップできるように、firebaseのcreateUserWithEmailAndPassword()を使います。

Login.vue

<template>
  <div>
    <div class="columns">
      <div class="column is-6 is-offset-3">
        <h1 class="title">ログイン</h1>
        <form @submit.prevent="login">
          <!-- メール -->
          <div class="field">
            <div class="control">
              <input type="text" placeholder="Email" v-model="email" class="input">        
            </div>
          </div>
          <!-- パスワード -->
          <div class="field">
            <div class="control">
              <input type="password" placeholder="Password" v-model="password" class="input">
            </div>
          </div>
          <!-- 送信ボタン -->
          <div class="field">
            <div class="control">
              <button class="button is-success">ログイン</button>
            </div>
          </div>
          <!-- エラー -->
          <article class="message is-danger" v-if="error">
            <div class="message-body">
              {{ error }}
            </div>
          </article>
        </form>
      </div>
    </div>
  </div>
</template>
<script>
// firebaseを使う importする④/5
import { projectAuth } from '../firebase/config.js'


export default {
  name: 'LogIn',
  data (){
    return {
      email: '',
      password: '',
      // authの状態を設定する1/2
      isAuthenticated: false,
      error: null,
    }
  },
  // authの状態を設定する2/2
  created() {
    projectAuth.onAuthStateChanged(user => {
      if(user) {
        this.isAuthenticated = true

        this.$router.push('/dashboard')
      }
    })
  },
  methods: {
    login () {
      console.log('Log In');

// Log in の場合はcreateUserWithEmailAndPasswordではなくsignInWithEmailAndPasswordを使う
      projectAuth.signInWithEmailAndPassword(this.email, this.password)
      .catch(err => this.error = err.message)
    },
    logout() {
      console.log('Log Out');
      projectAuth.signOut()
      .then(() => {
        this.isAuthenticated = false
      })
    }
  }
}</script>

ログインはサインアップとほとんど同じため、SignUp.vueからコピーを作成します。
サインアップからログインにするための主な変更点は次のとおりです。

  • Sign upなどの文言やメソッドをlog inに変更する
  • Slogin()メソッドをcreateUserWithEmailAndPasswordではなくsignInWithEmailAndPassword
  • Srouter/index.jsでpathを設定する
  • SApp.vueでrouter-linkをセットする

Dashboard.vue

<template>
  <div>
    <h1>ダッシュボード</h1>

    <div class="tabs">
      <ul>
        <li class="is-active"><a href="#">最新記事</a></li>
        <li v-for="category in categories" ><a href="#">{{ category }}</a></li>
      </ul>
    </div>
  </div>
</template>
<script>
export default {
  name: 'dashboard',
  data() {
    return {
      categories: ['Category1', 'Category2', 'Category3']
    }
  }
}}</script>

飛び先として作成します。

以上でシンプルなログインフォームが完成します。
あとは機能を拡充していって、必要に応じてコンポーネント化していきます。

Vue.js

Posted by devsakaso