kz’s blog

興味のあることについて書いていきます。

Vue.js でログイン機能を実装する

前提

この記事は@vue/cliを使用した内容となっております。

バージョン

"vue": "^2.5.17",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"

ページ構成

  • ホーム
  • プロフィール
  • ログイン

このうち、プロフィールはログイン認証が必要なページとします。

ソースファイル

上記ページ構成のファイルをそれぞれ用意します。

  • src/views/Home.vue
  • src/views/Profile.vue
  • src/views/Login.vue

※上2つの中身は適当で大丈夫です。ログインページは後述します。

ルーター設定

ソースコード

src/router.jsを編集します。

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import store from './store' // (1)

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/',
      component: Home
    },
    {
      path: '/profile',
      component: () => import('./views/Profile.vue'),
      meta: { requiresAuth: true }  // (2)
    },
    {
      path: '/login',
      component: () => import('./views/Login.vue')
    },
  ]
})

// (3)
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!store.getters.loggedIn) {
      next({
        path: '/login',
        query: {
          redirect: to.fullPath,
          message: true
        }
      })
    } else {
      next()
    }
  } else {
    next()
  }
})

export default router

説明

(1)

ログイン情報を参照するためstoreをインポートしておきます。

(2)

プロフィールページはログイン認証が必要なため、meta: { requiresAuth: true }を追加しておきます。

ここでのrequiresAuthは適宜変更して大丈夫です。

(3)

ページ遷移した際に、ログインしていない状態かつログイン認証が必要な場合は、ログインページに遷移するようにしています。

ログインページに遷移させる際、redirect: to.fullPathを与えて、ログイン完了後にもともと遷移しようとしていたページにリダイレクトできるようにしております。

message: trueに関しては、強制的にログインページに飛ばされた時用にメッセージを表示させるフラグになります。

ストア設定

ソースコード

src/store.jsを編集します。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    userId: ''
  },
  getters: {
    loggedIn: state => {
      return Boolean(state.userId.trim())
    }
  },
  mutations: {
    setUserId(state, userId) {
      state.userId = userId
    }
  },
  actions: {

  }
})

説明

ログインした際のユーザIDを保持しておくようにしています。

gettersloggedInでは、userIdに何らかの値がセットされている場合にtrueを返すようにしています。

ルートページの設定

ソースコード(テンプレート)

src/App.vueを編集します。

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/profile">Profile</router-link> |
      <a @click="logout()" v-if="$store.getters.loggedIn">Logout</a> <!-- (1) -->
      <router-link :to="'/login?redirect=' + $route.fullPath" v-else-if="$route.path !== '/login'">Login</router-link> <!-- (2) -->
    </div>
    <div v-if="$route.query.message">ログイン認証が必要なページです。</div> <!-- (3) -->
    <router-view/>
  </div>
</template>

説明

(1)

ログアウト処理をするためのリンクです。

ログインしている状態の時にだけ表示するようにしています。

(2)

ログインページに遷移するためのリンクです。

遷移先のパラメータにredirectを含めることで、ログイン処理後に元いたページにリダイレクトさせることができるようになります。

また、ログインしていない状態かつログインページ以外で表示するようにしています。

(3)

強制的にログインページに飛ばされた際に表示させるメッセージです。

ソースコード(スクリプト)

<script>
export default {
  methods: {
    logout () {
      this.$store.commit('setUserId', '')
      if (this.$route.meta.requiresAuth) {
        this.$router.push({
          path: '/login',
          query: { redirect: this.$route.fullPath }
        })
      }
    }
  }
}
</script>

説明

ストアで保持しているユーザIDを空にします。

また、ログインが必要なページでログアウトした際、強制的にログインページに飛ばすようにしています。

この時もやはりリダイレクトで戻って来られるようにパラメータを渡しています。

ログインページの設定

ソースコード(テンプレート)

<template>
  <div class="about">
    <h1>This is an login page</h1>
    <input v-model="userId"/>
    <button @click="login()" :disabled="!userId">ログイン</button>
  </div>
</template>

説明

ユーザID入力欄とログインボタンを設置しています。

ログインボタンは、ユーザIDが未入力の場合は非活性にしています。

ソースコード(スクリプト)

<script>
export default {
  data () {
    return {
      userId: ''
    }
  },
  methods: {
    login () {
      this.$store.commit('setUserId', this.userId) // (1)
      this.$router.push(this.$route.query.redirect) (2)
    }
  }
}
</script>

説明

(1)

入力したユーザIDでストアを更新しています。

(2)

元いたページにリダイレクトさせます。

参考

router.vuejs.org