LoginSignup
24
20

More than 5 years have passed since last update.

Quasar Framework(Vue.js) + Firebaseで、マテリアルデザインなログインフォームを実装する

Last updated at Posted at 2018-01-25

Vue.jsでマテリアルデザイン風なサイトが手軽に構築できるQuasar FrameworkとFirebaseで、ログイン機能を実装してみました。

Quasar Frameworkとは?

レスポンシブ対応で、マテリアルデザイン風のサイトが手軽に構築できるVue.js搭載のデザインフレームワークです。中身はVue.jsですので、Vue.jsが使える方は抵抗なく使えると思います。

Firebaseとは?

googleが提供するMBaasです。主にモバイル用途のようなのですが、普通に小さなウェブアプリとかなら使えるぽいです。

参考

http://quasar-framework.org/
https://medium.com/@anas.mammeri/vue-2-firebase-how-to-build-a-vue-app-with-firebase-authentication-system-in-15-minutes-fdce6f289c3c
https://qiita.com/sin_tanaka/items/ea149a33bd9e4b388241

環境

  • macOS High Sierra 10.13.2
  • npmがinstallされている

Quasar Framework をインストール・準備する

インストールして、開発サーバを起動させて動作を確認します。

# quasar-cliをinstall
$ npm install -g quasar-cli

# quasar init <スターターキット名> <プロジェクト名> 
$ quasar init default quasar-firebase

# プロジェクトフォルダに移動する。
$ cd quasar-firebase

# npmのpackageをinstallする。
$ npm install

# 開発サーバーでの起動
$ quasar dev

http://localhost:8080/にアクセスして、デモ画面が表示されていれば成功!

Signup.vue, Login.vueを作成する

Singup.vue
<template lang="html">
  <div>
    <div class="layout-padding row justify-center background-whitesmoke items-center">
      <div class="col-xs-12 col-sm-7 col-lg-5">
        <q-card class="q-card-background-white">
          <q-card-main>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-center">
                <img src="~assets/quasar-logo-full.svg" class="logo-sized">
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-left">
                <h5>新規登録</h5>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-left">
                <p style="font-size: 12px;">新規アカウントの登録をお願いします。</p>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1">
                <q-field>
                  <q-input v-model="email" float-label="メールアドレス" color="primary" type="email"/>
                </q-field>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1">
                <q-field>
                  <q-input v-model="password" float-label="パスワード" color="primary" type="password"/>
                </q-field>
              </div>
            </div>
            <div class="row" style="padding-top: 20px;">
              <div class="col-sm-10 offset-sm-1 text-right">
                <q-btn color="primary" style="font-weight: bold;" @click="signUp">新規登録</q-btn>
              </div>
            </div>
            <br>
            <div class="row">
              <p style="color:#027be3;font-size:12px;"><router-link to="/login">すでに登録済みの方はサインインしてください</router-link></p>
            </div>
          </q-card-main>
        </q-card>
      </div>
    </div>
  </div>
</template>

<script>
import {
  QBtn,
  QCard,
  QCardMain,
  QField,
  QInput
} from 'quasar'

export default {
  name: 'Signup',
  components: {
    QBtn,
    QCard,
    QCardMain,
    QField,
    QInput
  },
  data () {
    return {
      password: '',
      email: ''
    }
  }
}
</script>

<style lang="stylus">
.q-card-background-white
  background white

.background-whitesmoke
  background whitesmoke
  height 100vh

.logo-sized
  width 150px
  margin 20px
</style>
Login.vue
<template lang="html">
  <div>
    <div class="layout-padding row justify-center background-whitesmoke items-center">
      <div class="col-xs-12 col-sm-7 col-lg-5">
        <q-card class="q-card-background-white">
          <q-card-main>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-center">
                <img src="~assets/quasar-logo-full.svg" class="logo-sized">
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-left">
                <h5>ログイン</h5>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-left">
                <p style="font-size: 12px;">メールアドレスとパスワードを入力してください。</p>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1">
                <q-field>
                  <q-input v-model="email" float-label="メールアドレス" color="primary" type="email"/>
                </q-field>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1">
                <q-field>
                  <q-input v-model="password" float-label="パスワード" color="primary" type="password"/>
                </q-field>
              </div>
            </div>
            <div class="row" style="padding-top: 20px;">
              <div class="col-sm-10 offset-sm-1 text-right">
                <q-btn color="primary" style="font-weight: bold;" @click="signIn">ログイン</q-btn>
              </div>
            </div>
            <br>
            <div class="row">
              <p style="color:#027be3;font-size:12px;"><router-link to="/signup">新規アカウント作成</router-link></p>
            </div>
          </q-card-main>
        </q-card>
      </div>
    </div>
  </div>
</template>

<script>
import {
  QBtn,
  QCard,
  QCardMain,
  QField,
  QInput
} from 'quasar'

export default {
  name: 'Login',
  components: {
    QBtn,
    QCard,
    QCardMain,
    QField,
    QInput
  },
  data () {
    return {
      email: '',
      password: ''
    }
  }
}
</script>

<style lang="stylus">
.q-card-background-white
  background white

.background-whitesmoke
  background whitesmoke
  height 100vh

.logo-sized
  width 150px
  margin 20px
</style>

vue-routerの設定

quasar init で作成されたプロジェクトにはvue-routerも自動でインストールされていると思います。src/router.jsに設定します。

  • mode: 'history' に変更します。
  • routesに、login, singupのrouteを追記します。
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

function load (component) {
  // '@' is aliased to src/components
  return () => import(`@/${component}.vue`)
}

export default new VueRouter({
  mode: 'history',
  scrollBehavior: () => ({ y: 0 }),

  routes: [
    { path: '/', component: load('Hello') },
    { path: '/login', name: 'login', component: load('Login') },
    { path: '/signup', name: 'singup', component: load('Signup') },
    // Always leave this last one
    { path: '*', component: load('Error404') } // Not found
  ]
})

確認

ターミナルで、$ quasar devを実行している状態で、
http://localhost:8080/signup
http://localhost:8080/login
にそれぞれ、以下のように表示されれば成功です!

screen.png

Firebaseのインストール・設定

npmで、firebaseをインストールする

$ npm install --save firebase

Firebaseのプロジェクトの作成・設定

  • 次に、Firebaseのコンソール画面にログインします。(https://console.firebase.google.com/)
  • Firebaseのコンソール画面で、「プロジェクトを追加」から、プロジェクト名と、国/地域 を選択して、プロジェクトを作成します。
    ※コンソールへのログインは、googleアカウントが必要です。

  • 「ウェブアプリにFirebaseを追加する」をクリックします。

スクリーンショット 2018-01-25 21.26.39.png

  • 以下のようなコードが表記されると思います。
<script src="https://www.gstatic.com/firebasejs/4.8.1/firebase.js"></script>
<script>
  var config = {
    apiKey: "YOUR_KEY",
    authDomain: "quasar-YOUR_DOMAIN.firebaseapp.com",
    databaseURL: "https://YOUR_DOMAIN.firebaseio.com",
    projectId: "YOUR_ID",
    storageBucket: "YOUR_BUCKET_ID.appspot.com",
    messagingSenderId: "YOUR_SENDER_ID"
  };
  firebase.initializeApp(config);
</script>
  • src/main.jsに以下の3点を追記します。
    • config部分をコピペする
    • firebaseをimportする
    • firebaseのinitializeAppを実行する
src/main.js
require(`quasar/dist/quasar.${__THEME}.css`)

import Vue from 'vue'
import Quasar from 'quasar'
import router from './router'

// firebaseをimportします
import firebase from 'firebase'

Vue.config.productionTip = false
Vue.use(Quasar) // Install Quasar Framework

if (__THEME === 'mat') {
  require('quasar-extras/roboto-font')
}
import 'quasar-extras/material-icons'

// config部分をコピペします
var config = {
  apiKey: 'YOUR_KEY',
  authDomain: 'quasar-firebase.firebaseapp.com',
  databaseURL: 'https://YOUR_DOMAIN.firebaseio.com',
  projectId: 'YOUR_ID',
  storageBucket: 'YOUR_BUCKET_ID.appspot.com',
  messagingSenderId: 'YOUR_SENDER_ID'
}

// firebaseの初期化設定します
firebase.initializeApp(config)

Quasar.start(() => {
  /* eslint-disable no-new */
  new Vue({
    el: '#q-app',
    router,
    render: h => h(require('./App').default)
  })
})

Firebaseの認証の設定

Firebaseのコンソール画面から、プロジェクト画面を開いて、「Authentication」にメール/パスワードの認証を有効にします。

スクリーンショット 2018-01-25 21.02.16.png

新規ユーザーの登録メソッドを追記

  • firebase.auth().createUserWithEmailAndPassword()を使います。
Signup.vue
import firebase from 'firebase'
...
<script>
...
  methods: {
    signUp: function () {
      firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
        .then(user => {
          alert('アカウントの新規作成が完了しました!', user.email)
        })
        .catch(error => {
          var errorCode = error.code
          var errorMessage = error.message
          alert(errorCode, errorMessage)
        })
    }
  }
...
</script>
...

ユーザー認証のメソッドを追記する。

  • firebase.auth().signInWithEmailAndPasswordを利用して
Login.vue
...
<script>
...
import firebase from 'firebase'
...
  methods: {
    signIn: function () {
      firebase.auth().signInWithEmailAndPassword(this.email, this.password)
        .then(user => {
          alert('無事ログインしました!')
        })
        .catch(err => {
          alert(err)
        })
    }
...
</script>
...

vue-routerでリダイレクトの設定をする

  • src/routes.js に次のように設定します。
routes.js
...
  routes: [
    { path: '/', component: load('Hello'), meta: { requiresAuth: true } },
    { path: '/login', name: 'login', component: load('Login') },
    { path: '/signup', name: 'singup', component: load('Signup') },
    // Always leave this last one
    { path: '*', component: load('Error404') } // Not found
  ]
...
  • さらに、src/main.jsに、ログインしていない状態でホーム画面にアクセスすると、login画面にリダイレクトするように設定します。
main.js
...
firebase.initializeApp(config)

// ここを追加
router.beforeEach((to, from, next) => {
  let currentUser = firebase.auth().currentUser
  let requiresAuth = to.matched.some(record => record.meta.requiresAuth)

  if (requiresAuth && !currentUser) {
    next('login')
  }
  else if (!requiresAuth && currentUser) {
    next('hello')
  }
  else {
    next()
  }
})

Quasar.start(() => {
  /* eslint-disable no-new */
  new Vue({
    el: '#q-app',
    router,
    render: h => h(require('./App').default)
  })
})
  • http://localhost:8080/にアクセス→http://localhost:8080/loginにリダイレクト→ログイン実行→ログイン成功のalertが表示されて、http://localhost:8080/にアクセスされていれば成功です!ただ、リロードすると、またもやログイン画面に戻ってしまいます。。。これを解決するには以下の手順が必要です。

routerの再設定

さきほどセットしたbeforeEachは、firebaseの初期化の前に呼び出されているので、初期化が完了したときには、firebase.auth().currentUserがnullを返してしまい、それが原因で、ログイン画面にリダイレクトされているようです。

Firebaseでは、AuthオブジェクトにObserverを設定することができます。onAuthStateChanged を利用して、Firebaseが初期化されたことが確認された場合にのみ、Vueアプリケーションを初期化するようにします。(Authの状態が中途半端な状態にならないということかな。)

main.jsに、コードを追記します。

main.js
let app
firebase.auth().onAuthStateChanged(function (user) {
  Quasar.start(() => {
    if (!app) {
      /* eslint-disable no-new */
      app = new Vue({
        el: '#q-app',
        router,
        render: h => h(require('./App').default)
      })
    }
  })
})

ログアウト機能をHello.vueに追記する。

Hello.vueにログアウト機能を実装します。今回はq-toolbarの右端にログアウトボタンをつけてみました。

Hello.vue
...
<q-toolbar slot="header" class="glossy">
      <q-btn
        flat
        @click="$refs.layout.toggleLeft()"
      >
        <q-icon name="menu" />
      </q-btn>

      <q-toolbar-title>
        Quasar App
        <div slot="subtitle">Running on Quasar v{{$q.version}}</div>
      </q-toolbar-title>
      <q-btn outline @click="logout">ログアウト</q-btn>
    </q-toolbar>

...

import firebase from 'firebase'

...

logout () {
      firebase.auth().signOut()
        .then(() => {
          alert('ログアウトしました!')
          this.$router.replace('login')
        })
    }
...

これでサインアップ、ログイン、ログアウトまで、ひとまず完成です!

まとめ

サインアップ、ログイン、ログアウトまで大体15分くらいで、できてしまうので、firebaseかなり便利そうだな〜という印象です。

Quasar Frameworkも、ほとんどvue.jsの知識でサクッといい感じのデザインのページが作れてしまうので、マテリアルデザインに抵抗が無い人はおすすめです!

24
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
20