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

プログラミング
この記事は約8分で読めます。
スポンサーリンク

Nuxt をインストールする

インストール
ここでは、4 つのステップで、Nuxt プロジェクトを立ち上げで実行する方法について説明します。
$ npx create-nuxt-app <project-name>

いくつかの質問に対する設定値

状況に応じて選択してください。

以下、筆者が普段選択するものを記載します。

質問入力値
サーバーサイドのフレームワークNone
UI フレームワークVuetfy
※このページでは Vuetfy を使用して進めていきます。
テスティングフレームワークNone
Nuxt のモード・簡単なアプリの場合 SPA
・ちょっと凝ったアプリの場合 Universal
※あとからでも変更できます
axios筆者は firebase が好きなのでをサーバーサイドの実装はあまりしないので追加しません。
サーバーサイドを自前で用意する場合や、外部サービスと連携させる場合は追加します。
EsLint追加する
Prettier追加する

起動してみる

$ npm run dev
http://localhost:3000

上記 URL にアクセスし、画面が表示されれば OK です。

画面を作成する

まずはじめに画面構成をお伝えしておきます。

画面構成

  • ホーム画面(ログインを行う)
  • 認証が必要な画面
  • 認証が不要な画面

ログインしていない状態で認証が必要な画面にアクセスするとホーム画面に飛ばされます。

認証が必要な画面を作成する

pages/authentication-required.vue

<template>
  <div>
    認証が必要な画面です。
  </div>
</template>

ひとまず、テンプレート部分だけ作成します。

見ての通り、文字を表示させているだけです。

後ほどスクリプトも記述します。

認証が不要な画面を作成する

pages/authentication-not-required.vue

<template>
<div>
認証が不要な画面です。
</div>
</template>

こちらも文字を表示させているだけです。

スクリプトは特に記述しないので、これで完成です。

デフォルトのレイアウトを変更する

layouts/default.vue

<template>
  <v-app dark>
    <v-tabs fixed-tabs hide-slider>
      <v-tab to="/">
        ホーム
      </v-tab>
      <v-tab to="/authentication-not-required">
        認証不要
      </v-tab>
      <v-tab to="/authentication-required">
        認証必要
      </v-tab>
    </v-tabs>

    <v-content>
      <v-container>
        <nuxt />
      </v-container>
    </v-content>
  </v-app>
</template>

上部にツールバーを表示させ、ホーム画面/認証が不要な画面/認証が必要な画面に遷移できるようにしています。

下半分の <nuxt /> の部分はそれぞれのページを表示する領域になります。

ここまでの画面確認

http://localhost:3000

上記 URL にアクセスすると、インストール直後に起動した画面の上部にツールバーが追加されていると思います。

ツールバーをクリックした際、該当のページに遷移されるようになっていれば OK です。

ストアを作成する

ログイン状態を保持させるためにストア(Vuex)を作成します。

store/index.js

export const state = () => ({
  loggedIn: false
})

export const mutations = {
  login(state) {
    state.loggedIn = true
  },
  logout(state) {
    state.loggedIn = false
  }
}

state にログイン状態を bool 値で保持させ、

mutations にログイン時、ログアウト時に使用するファンクションを定義します。

※ストアの javascript ファイルを新規追加した場合は、ローカルサーバーを再起動させてください。(最近のバージョンではストアファイルの追加もウォッチするようになったようです)

ミドルウェアを作成する

ログインしていない状態で、認証が必要な画面に遷移した場合、ホーム画面に強制的に飛ばすために必要になります。

middleware/authenticated.js

export default ({ store, redirect, route }) => {
  // ログインしていない場合ホームにリダイレクトします。
  if (!store.state.loggedIn) {
    return redirect({
      path: '/',
      query: {
        showMessage: true,
        redirect: route.path
      }
    })
  }
}

強制的にホーム画面に飛ばされた後にログイン処理をした場合、もともと表示していた画面に戻すために、クエリに redurect を設定しています。

また、警告メッセージを出したいので、showMessage を設定しています。

認証が必要な画面を修正する

ミドルウェアを作成しただけの状態では、ログインしていなくても認証が必要な画面に行けてしまうので、修正を行います。

上の方に書かれていますが、ここでスクリプトを追加します。

pages/authentication-required.vue

<script>
export default {
  middleware: 'authenticated'
}
</script>

ミドルウェア authenticated を使いますよー。と宣言しています。

こうすることで、ログインしていない状態でこのページに行こうとすると強制的にホーム画面に飛ばされるようになります。

ホーム画面(ログインする画面)を作成する

最後にログイン機能を持たせたホーム画面を作成します。

pages/index.vue

<template>
  <v-layout column>
    <template v-if="$store.state.loggedIn">
      <v-flex>
        <v-btn color="primary" @click="logout()">
          logout
        </v-btn>
      </v-flex>
    </template>

    <template v-else>
      <v-flex>
        <v-alert
          :value="$route.query.showMessage"
          color="warning"
          icon="priority_high"
          outline
        >
          ログイン認証してください。
        </v-alert>
      </v-flex>

      <v-flex>
        <v-btn color="primary" @click="login()">
          login
        </v-btn>
      </v-flex>
    </template>
  </v-layout>
</template>

ログイン状態によって、ログイン/ログアウトボタンを表示させ、認証が必要な画面から強制的に飛ばされた場合は、アラートメッセージを出すようにしています。

pages/index.vue

<script>
export default {
  methods: {
    login() {
      this.$store.commit('login')

      // URL のクエリにリダイレクトが存在する場合はリダイレクトします。
      if (this.$route.query.redirect) {
        this.$router.push(this.$route.query.redirect)
      }
    },

    logout() {
      this.$store.commit('logout')
    }
  }
}
</script>

ログイン/ログアウトボタンを押した際、ストアにログイン状態を反映させています。

また、ログインする際、URL のクエリに redirect が存在する場合は、そのパスにリダイレクトさせるようにしています。

最終確認

ログインしていない状態で、認証が必要な画面に行こうとすると、強制的にホーム画面に戻され、アラートメッセージが表示されていると思います。

また、その状態で、ログインをすると、認証が必要な画面に戻されるようになっていると思います。

コメント

タイトルとURLをコピーしました