【サンプル付き】Vuetifyでログイン画面のテンプレートを作る - inokawablog

【サンプル付き】Vuetifyでログイン画面のテンプレートを作る

よくあるログイン画面を作っていきます。

毎度毎度同じようなものを作っている気がしたので、テンプレートを残しておきます。

typescriptを使用しています。

vuetify typescript
2.2.12 3.8

完成デザイン

完成デザインです。大体のサービスのフォームはこんな感じになっているんじゃないかなと思います。

Vuetifyでログイン画面を作る

共通部分

layouts/auth.vue

<template>
  <v-app>
    <v-app-bar height="128px" color="#F5F5F5" dense flat>
      <div class="header-title justify-center d-flex fill-width">
        <nuxt-link to="/">
          <img src="~/static/v.png" style="height:48px" />
        </nuxt-link>
      </div>
    </v-app-bar>
    <v-content style="background:#F5F5F5;height: auto;" class="pa-0 fill-height">
      <v-container :class="{ 'pa-0': $vuetify.breakpoint.sm || $vuetify.breakpoint.xs }">
        <nuxt />
      </v-container>
    </v-content>
    <footer style="background: #F5F5F5">
      <div class="pa-8 d-flex flex-warp justify-center fill-wdith">
        <nuxt-link to="privacy" class="link-caption mr-8">プライバシーポリシー</nuxt-link>
        <nuxt-link to="tos" class="link-caption mr-8">利用規約</nuxt-link>
      </div>
    </footer>
  </v-app>
</template>

登録フォーム

extendを使って書いています。

pages/reister.vue

<template>
  <div>
    <v-card
      :tile="$vuetify.breakpoint.sm || $vuetify.breakpoint.xs"
      class="mx-auto fill-width"
      flat
      max-width="640"
    >
      <v-card-title class="text-center pa-8">
        <h4 class="fill-width">会員情報入力</h4>
      </v-card-title>
      <v-divider> </v-divider>
      <div class="px-6 py-8">
        <div style="max-width:344px" class="mx-auto">
          <div>
            <v-btn
              class="fill-width text-capitalize caption"
              height="48px"
              outlined
              style="border-color:#979797;"
              tile
            >
              <img
                class="button-logo-img mr-4"
                src="https://madeby.google.com/static/images/google_g_logo.svg"
                style="height:24px;"
              />
              Googleで登録
            </v-btn>
            <v-btn
              class="fill-width mt-5 text-capitalize caption"
              color="#385184"
              dark
              depressed
              height="48px"
              tile
            >
              <img
                class="button-logo-img mr-4"
                src="~/static/f_logo_RGB-White_1024.png"
                style="height:24px;"
              />
              Facebookで登録
            </v-btn>
          </div>
          <div class="separator separator_login_page">
            <div class="middle_separator">または</div>
          </div>
          <div class="pt-6">
            <div>
              <v-text-field
                v-model="email"
                :rules="[emailRules.required, emailRules.regex]"
                autofocus
                dense
                height="48px"
                outlined
                placeholder="メールアドレス"
              ></v-text-field>

              <v-text-field
                v-model="password"
                :append-icon="passwordShow ? 'mdi-eye' : 'mdi-eye-off'"
                :rules="[passwordRules.required, passwordRules.regex]"
                :type="passwordShow ? 'text' : 'password'"
                dense
                height="48px"
                name="input-password"
                outlined
                placeholder="パスワード"
                @click:append="passwordShow = !passwordShow"
              ></v-text-field>
            </div>
            <div class="login-btn pb-8">
              <v-btn
                class="fill-width caption"
                color="#FFCB00"
                depressed
                height="48px"
                tile
              >
                会員登録
              </v-btn>
            </div>
            <v-divider></v-divider>
            <div class="pt-8 pb-4">
              <span>すでにアカウントをお持ちですか?</span>
              <nuxt-link to="/login">ログインに移動</nuxt-link>
            </div>
          </div>
        </div>
      </div>
    </v-card>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  layout: 'auth',
  data() {
    return {
      email: null,
      emailRules: {
        required: (value: string | boolean) =>
          !!value || 'メールアドレスは必須です',
        regex: (value: any) =>
          /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
            value
          ) || 'メールアドレスの形式が違います'
      },
      password: null,
      passwordShow: false,
      passwordRules: {
        required: (value: string | boolean) =>
          !!value || 'パスワードは必須です',
        regex: (value: any) =>
          /^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)[a-zA-Z\d]{8,128}$/.test(value) ||
          '半角英小文字大文字数字をそれぞれ1種類以上含む7文字以上128文字以下で入力してください'
      }
    }
  }
})
</script>

scss

.fill-width {
  width: 100%;
}
.link-caption {
  text-decoration: none;
  color: #666 !important;
  font-size: .75rem;
}
.separator {
  margin-top: 30px;
  margin-bottom: 30px;
  height: 0;
  border-top: 1px solid #ddd;
  border-bottom: 1px solid #fff;
  position: relative;
}
.middle_separator {
  position: absolute;
  padding: 0 16px;
  color: #ccc;
  background: #fff;
  font-size: 11px;
  text-shadow: 0 1px 0 #fff;
  text-transform: uppercase;
  top: -7px;
  left: 30%;
}
.middle_separator {
  color: #777;
  font-size: 13px;
  top: -9px;
  left: 41%;
}

facebookのロゴは自前で用意してください。

facebook logo download

おまけ

会員登録やログインでバリデーションを共通化させているなら、mixinで共通化させた方が綺麗です。

<script lang="ts">
import Vue from 'vue'
import FormValidation from '../mixins/FormValidation.vue'

export default Vue.extend({
  mixins: [FormValidation],
  layout: 'auth',
  data() {
    return {
      email: null,
      password: null,
      passwordShow: false
    }
  }
})
</script>

mixins/FormValidation.vue

<script>
// バリデーションルールに関してのみ
// バリデーション共通化
export default {
  data() {
    return {
      emailRules: {
        required: (value) => !!value || 'メールアドレスは必須です',
        regex: (value) =>
          /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
            value
          ) || 'メールアドレスの形式が違います'
      },
      passwordRules: {
        required: (value) => !!value || 'パスワードは必須です',
        regex: (value) =>
          /^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)[a-zA-Z\d]{8,128}$/.test(value) ||
          '半角英小文字大文字数字をそれぞれ1種類以上含む7文字以上128文字以下で入力してください'
      }
    }
  }
}
</script>