Nuxt.jsでのログイン実装
現在ユーザー機能が必要なアプリケーションを作成しているため,ログイン機能を実装する必要があります。
Firebase Authenticationの機能を使って登録したユーザーがログインできるかを確認します。
前提
・Firebaseが使える状態にある
・axiosがインストール済みである
ページ構成
よくあるヘッダーの右側にログイン、サインインがあるパターンを想定します。
こんな感じです。
まずはリンク先のページをpages配下に用意してあげましょう。
touch pages/login.vue
続いてヘッダーにリンクを用意してあげましょう。
Nuxtはルーティングが簡単にできるからとても便利ですね。
<ul class="list-inline">
<li class="list-inline-item"><n-link to="/login">Log in</n-link></li>
</ul>
loginフォームを用意する
シンプルなフォームがほしかったためこちらからお借りしました。
Firebase Authenticationでユーザーを用意
1.Authenticationをクリック
2.ユーザーを追加をクリック
3.メールアドレスとパスワードを入力(存在しないもので構いません)
4.ユーザーを追加をクリック
Sign-in methodの設定
1.Sign-in methodをクリック
2.メール/パスワードを有効化
plugins/firebase.jsを用意
firebaseの情報を設定します。
1.プロジェクトの概要 > 歯車をクリック > プロジェクトを設定をクリック
2.全般をスクロールする
こちらの画面をスクロールすると表示される情報ですね。
const config = {
apiKey: "{{ APIKEY }}",
authDomain: "{{ AUTHDOMAIN }}",
databaseURL: "{{ DATABASEURL }}",
projectId: "{{ PROJECTID }}",
storageBucket: "{{ STORAGEBUCKET }}",
messagingSenderId: "{{ MESSAGINGSENDERID }}",
appId: "{{ APPID }}",
measurementId: "{{ MESUREMENTID }}"
};
// Initialize Firebase
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
export default firebase;
storeを用意する
データを保存しておくという仕組みしか理解しておりませんので、提供いただいたコードをそのまま掲載します。
import firebase from '~/plugins/firebase'
// data保管庫
export const state = () => ({
user: {
uid: '',
email: '',
login: false,
},
})
// stateの情報を取得
export const getters = {
user: state => {
return state.user;
}
}
// storeの上書き以外の処理や非同期通信
export const actions = {
login({ dispatch }, payload) {
// メールとパスワードでログイン
console.log('login action');
firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
.then(user => {
console.log('ログイン成功!');
this.$router.replace({ path: '/' });
dispatch('checkLogin')
})
.catch((error) => {
alert(error);
})
},
loginGoogle({ dispatch }) {
// Googleアカウントでログイン
console.log('loginGoogle action');
const provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider)
.then(result => {
const user = result.user;
console.log('googleログイン成功!');
dispatch('checkLogin');
})
.catch((error) => {
alert(error);
});
},
checkLogin({ commit }) {
// ログインしているかどうかのチェックログインしていたらデータ追加
firebase.auth().onAuthStateChanged((user) => {
console.log(user);
if (user) {
console.log(user);
commit('login', { uid: user.uid, email: user.email });
}
})
},
logout({ commit }) {
// ログアウト
firebase.auth().signOut()
.then(() => {
console.log("ログアウトしました");
commit('logout');
})
.catch((error) => {
console.log(`ログアウト時にエラーが発生しました (${error})`);
});
}
}
// stateの上書き(代入)
export const mutations = {
login(state, payload) {
state.user.uid = payload.uid;
state.user.email = payload.email;
state.user.login = true;
},
logout(state) {
state.user.uid = '';
state.user.email = '';
state.user.login = false;
}
}
ここまでで下準備が終わりました
login.vueから実処理を行うLoginMenuのコンポーネントを呼び出します
<template>
<div>
<h1>Log In</h1>
<LoginMenu />
<h3 v-if="user.login">
ログインしました
</h3>
<h3 class="title" v-else>
ログインしてください
</h3>
</div>
</template>
<script>
import LoginMenu from "@/components/loginMenu.vue";
export default {
components: {
LoginMenu: LoginMenu,
},
computed: {
user() {
return this.$store.getters["user"];
},
}
};
</script>
<template>
<div class="login-page">
<div class="form">
<div class="register-form" v-if="this.$route.path === '/signup'">
<input type="text" placeholder="name"/>
<input type="password" placeholder="password"/>
<input type="text" placeholder="email address"/>
<button>create</button>
<p class="message">Already registered? <n-link to="/login">Sign In</n-link></p>
</div>
<div class="login-form" v-else>
<input type="text" v-model="email" placeholder="username"/>
<input type="password" v-model="password" placeholder="password"/>
<button v-on:click="login">login</button>
<p class="message">Not registered? <n-link to="/signup">Create an account</n-link></p>
</div>
</div>
</div>
</template>
<script>
export default {
computed: {
// dataのように扱える
// dataを作る前処理が必要な際に利用
user () {
return this.$store.getters['user'];
},
},
data () {
return {
email: '',
password: '',
}
},
mounted() {
// ログインしているかどうかのチェックログインしていたらデータ追加
this.$store.dispatch('checkLogin');
},
methods : {
async login () {
// メールとパスワードでログイン
console.log('login action', this.email, this.password);
this.$store.dispatch('login', {email:this.email, password:this.password});
},
loginGoogle() {
// Googleアカウントでログイン
this.$store.dispatch('loginGoogle');
},
logout : function() {
// ログアウト
this.$store.dispatch('logout');
}
}
}
</script>
ログイン可能か確認する
ひとまずログインを行うと右のメニューがlogoutになるか確認します。
<template>
<nav class="navbar navbar-light bg-light">
<h1><n-link to="/">title</n-link></h1>
<ul class="list-inline" v-if="user.login">
<li class="list-inline-item"><n-link to="/logout" >Log Out</n-link></li>
</ul>
<ul class="list-inline" v-else>
<li class="list-inline-item"><n-link to="/login">Log in</n-link></li>
<li class="list-inline-item"><n-link to="/signup">Sign up</n-link></li>
</ul>
</nav>
</template>
nuxt.jsとFirebase Authenticationでログインフォームからログイン#protoout pic.twitter.com/rDzU3q17P6
— ウーリズム (@Uh_rhythm) October 14, 2020
ひとまず作りながら覚えていく
Nuxt.jsは以前から何度か触れていましたが複数ページにまたがる物を作るのは今回が初めてだったため
作りながら覚えていくことになります。
ひとまずstoreやstateについて早急に学んでいく必要がありますね。