よくあるログイン画面を作っていきます。
毎度毎度同じようなものを作っている気がしたので、テンプレートを残しておきます。
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のロゴは自前で用意してください。
おまけ
会員登録やログインでバリデーションを共通化させているなら、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>